root/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hdmi_wp_dump
  2. hdmi_wp_get_irqstatus
  3. hdmi_wp_set_irqstatus
  4. hdmi_wp_set_irqenable
  5. hdmi_wp_clear_irqenable
  6. hdmi_wp_set_phy_pwr
  7. hdmi_wp_set_pll_pwr
  8. hdmi_wp_video_start
  9. hdmi_wp_video_stop
  10. hdmi_wp_video_config_format
  11. hdmi_wp_video_config_interface
  12. hdmi_wp_video_config_timing
  13. hdmi_wp_init_vid_fmt_timings
  14. hdmi_wp_audio_config_format
  15. hdmi_wp_audio_config_dma
  16. hdmi_wp_audio_enable
  17. hdmi_wp_audio_core_req_enable
  18. hdmi_wp_init
  19. hdmi_wp_get_audio_dma_addr

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * HDMI wrapper
   4  *
   5  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
   6  */
   7 
   8 #define DSS_SUBSYS_NAME "HDMIWP"
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/err.h>
  12 #include <linux/io.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/seq_file.h>
  15 
  16 #include "omapdss.h"
  17 #include "dss.h"
  18 #include "hdmi.h"
  19 
  20 void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s)
  21 {
  22 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r))
  23 
  24         DUMPREG(HDMI_WP_REVISION);
  25         DUMPREG(HDMI_WP_SYSCONFIG);
  26         DUMPREG(HDMI_WP_IRQSTATUS_RAW);
  27         DUMPREG(HDMI_WP_IRQSTATUS);
  28         DUMPREG(HDMI_WP_IRQENABLE_SET);
  29         DUMPREG(HDMI_WP_IRQENABLE_CLR);
  30         DUMPREG(HDMI_WP_IRQWAKEEN);
  31         DUMPREG(HDMI_WP_PWR_CTRL);
  32         DUMPREG(HDMI_WP_DEBOUNCE);
  33         DUMPREG(HDMI_WP_VIDEO_CFG);
  34         DUMPREG(HDMI_WP_VIDEO_SIZE);
  35         DUMPREG(HDMI_WP_VIDEO_TIMING_H);
  36         DUMPREG(HDMI_WP_VIDEO_TIMING_V);
  37         DUMPREG(HDMI_WP_CLK);
  38         DUMPREG(HDMI_WP_AUDIO_CFG);
  39         DUMPREG(HDMI_WP_AUDIO_CFG2);
  40         DUMPREG(HDMI_WP_AUDIO_CTRL);
  41         DUMPREG(HDMI_WP_AUDIO_DATA);
  42 }
  43 
  44 u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp)
  45 {
  46         return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
  47 }
  48 
  49 void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus)
  50 {
  51         hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus);
  52         /* flush posted write */
  53         hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS);
  54 }
  55 
  56 void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask)
  57 {
  58         hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask);
  59 }
  60 
  61 void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask)
  62 {
  63         hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask);
  64 }
  65 
  66 /* PHY_PWR_CMD */
  67 int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val)
  68 {
  69         /* Return if already the state */
  70         if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val)
  71                 return 0;
  72 
  73         /* Command for power control of HDMI PHY */
  74         REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6);
  75 
  76         /* Status of the power control of HDMI PHY */
  77         if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val)
  78                         != val) {
  79                 DSSERR("Failed to set PHY power mode to %d\n", val);
  80                 return -ETIMEDOUT;
  81         }
  82 
  83         return 0;
  84 }
  85 
  86 /* PLL_PWR_CMD */
  87 int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val)
  88 {
  89         /* Command for power control of HDMI PLL */
  90         REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2);
  91 
  92         /* wait till PHY_PWR_STATUS is set */
  93         if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val)
  94                         != val) {
  95                 DSSERR("Failed to set PLL_PWR_STATUS\n");
  96                 return -ETIMEDOUT;
  97         }
  98 
  99         return 0;
 100 }
 101 
 102 int hdmi_wp_video_start(struct hdmi_wp_data *wp)
 103 {
 104         REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31);
 105 
 106         return 0;
 107 }
 108 
 109 void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
 110 {
 111         int i;
 112 
 113         hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE);
 114 
 115         REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);
 116 
 117         for (i = 0; i < 50; ++i) {
 118                 u32 v;
 119 
 120                 msleep(20);
 121 
 122                 v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW);
 123                 if (v & HDMI_IRQ_VIDEO_FRAME_DONE)
 124                         return;
 125         }
 126 
 127         DSSERR("no HDMI FRAMEDONE when disabling output\n");
 128 }
 129 
 130 void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
 131                 const struct hdmi_video_format *video_fmt)
 132 {
 133         u32 l = 0;
 134 
 135         REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode,
 136                 10, 8);
 137 
 138         l |= FLD_VAL(video_fmt->y_res, 31, 16);
 139         l |= FLD_VAL(video_fmt->x_res, 15, 0);
 140         hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l);
 141 }
 142 
 143 void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
 144                                     const struct videomode *vm)
 145 {
 146         u32 r;
 147         bool vsync_inv, hsync_inv;
 148         DSSDBG("Enter hdmi_wp_video_config_interface\n");
 149 
 150         vsync_inv = !!(vm->flags & DISPLAY_FLAGS_VSYNC_LOW);
 151         hsync_inv = !!(vm->flags & DISPLAY_FLAGS_HSYNC_LOW);
 152 
 153         r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);
 154         r = FLD_MOD(r, 1, 7, 7);        /* VSYNC_POL to dispc active high */
 155         r = FLD_MOD(r, 1, 6, 6);        /* HSYNC_POL to dispc active high */
 156         r = FLD_MOD(r, vsync_inv, 5, 5);        /* CORE_VSYNC_INV */
 157         r = FLD_MOD(r, hsync_inv, 4, 4);        /* CORE_HSYNC_INV */
 158         r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 3, 3);
 159         r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
 160         hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);
 161 }
 162 
 163 void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
 164                                  const struct videomode *vm)
 165 {
 166         u32 timing_h = 0;
 167         u32 timing_v = 0;
 168         unsigned int hsync_len_offset = 1;
 169 
 170         DSSDBG("Enter hdmi_wp_video_config_timing\n");
 171 
 172         /*
 173          * On OMAP4 and OMAP5 ES1 the HSW field is programmed as is. On OMAP5
 174          * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsync_len-1.
 175          * However, we don't support OMAP5 ES1 at all, so we can just check for
 176          * OMAP4 here.
 177          */
 178         if (wp->version == 4)
 179                 hsync_len_offset = 0;
 180 
 181         timing_h |= FLD_VAL(vm->hback_porch, 31, 20);
 182         timing_h |= FLD_VAL(vm->hfront_porch, 19, 8);
 183         timing_h |= FLD_VAL(vm->hsync_len - hsync_len_offset, 7, 0);
 184         hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);
 185 
 186         timing_v |= FLD_VAL(vm->vback_porch, 31, 20);
 187         timing_v |= FLD_VAL(vm->vfront_porch, 19, 8);
 188         timing_v |= FLD_VAL(vm->vsync_len, 7, 0);
 189         hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);
 190 }
 191 
 192 void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
 193                 struct videomode *vm, const struct hdmi_config *param)
 194 {
 195         DSSDBG("Enter hdmi_wp_video_init_format\n");
 196 
 197         video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
 198         video_fmt->y_res = param->vm.vactive;
 199         video_fmt->x_res = param->vm.hactive;
 200 
 201         vm->hback_porch = param->vm.hback_porch;
 202         vm->hfront_porch = param->vm.hfront_porch;
 203         vm->hsync_len = param->vm.hsync_len;
 204         vm->vback_porch = param->vm.vback_porch;
 205         vm->vfront_porch = param->vm.vfront_porch;
 206         vm->vsync_len = param->vm.vsync_len;
 207 
 208         vm->flags = param->vm.flags;
 209 
 210         if (param->vm.flags & DISPLAY_FLAGS_INTERLACED) {
 211                 video_fmt->y_res /= 2;
 212                 vm->vback_porch /= 2;
 213                 vm->vfront_porch /= 2;
 214                 vm->vsync_len /= 2;
 215         }
 216 
 217         if (param->vm.flags & DISPLAY_FLAGS_DOUBLECLK) {
 218                 video_fmt->x_res *= 2;
 219                 vm->hfront_porch *= 2;
 220                 vm->hsync_len *= 2;
 221                 vm->hback_porch *= 2;
 222         }
 223 }
 224 
 225 void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
 226                 struct hdmi_audio_format *aud_fmt)
 227 {
 228         u32 r;
 229 
 230         DSSDBG("Enter hdmi_wp_audio_config_format\n");
 231 
 232         r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
 233         if (wp->version == 4) {
 234                 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
 235                 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
 236         }
 237         r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
 238         r = FLD_MOD(r, aud_fmt->type, 4, 4);
 239         r = FLD_MOD(r, aud_fmt->justification, 3, 3);
 240         r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
 241         r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
 242         r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
 243         hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r);
 244 }
 245 
 246 void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
 247                 struct hdmi_audio_dma *aud_dma)
 248 {
 249         u32 r;
 250 
 251         DSSDBG("Enter hdmi_wp_audio_config_dma\n");
 252 
 253         r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2);
 254         r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
 255         r = FLD_MOD(r, aud_dma->block_size, 7, 0);
 256         hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r);
 257 
 258         r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL);
 259         r = FLD_MOD(r, aud_dma->mode, 9, 9);
 260         r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
 261         hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r);
 262 }
 263 
 264 int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable)
 265 {
 266         REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31);
 267 
 268         return 0;
 269 }
 270 
 271 int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
 272 {
 273         REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30);
 274 
 275         return 0;
 276 }
 277 
 278 int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp,
 279                  unsigned int version)
 280 {
 281         struct resource *res;
 282 
 283         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp");
 284         wp->base = devm_ioremap_resource(&pdev->dev, res);
 285         if (IS_ERR(wp->base))
 286                 return PTR_ERR(wp->base);
 287 
 288         wp->phys_base = res->start;
 289         wp->version = version;
 290 
 291         return 0;
 292 }
 293 
 294 phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp)
 295 {
 296         return wp->phys_base + HDMI_WP_AUDIO_DATA;
 297 }

/* [<][>][^][v][top][bottom][index][help] */