root/drivers/video/fbdev/omap2/omapfb/dss/venc.c

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

DEFINITIONS

This source file includes following definitions.
  1. venc_write_reg
  2. venc_read_reg
  3. venc_write_config
  4. venc_reset
  5. venc_runtime_get
  6. venc_runtime_put
  7. venc_timings_to_config
  8. venc_power_on
  9. venc_power_off
  10. venc_display_enable
  11. venc_display_disable
  12. venc_set_timings
  13. venc_check_timings
  14. venc_get_timings
  15. venc_get_wss
  16. venc_set_wss
  17. venc_set_type
  18. venc_invert_vid_out_polarity
  19. venc_init_regulator
  20. venc_dump_regs
  21. venc_get_clocks
  22. venc_connect
  23. venc_disconnect
  24. venc_init_output
  25. venc_uninit_output
  26. venc_probe_of
  27. venc_bind
  28. venc_unbind
  29. venc_probe
  30. venc_remove
  31. venc_runtime_suspend
  32. venc_runtime_resume
  33. venc_init_platform_driver
  34. venc_uninit_platform_driver

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * linux/drivers/video/omap2/dss/venc.c
   4  *
   5  * Copyright (C) 2009 Nokia Corporation
   6  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
   7  *
   8  * VENC settings from TI's DSS driver
   9  */
  10 
  11 #define DSS_SUBSYS_NAME "VENC"
  12 
  13 #include <linux/kernel.h>
  14 #include <linux/module.h>
  15 #include <linux/clk.h>
  16 #include <linux/err.h>
  17 #include <linux/io.h>
  18 #include <linux/mutex.h>
  19 #include <linux/completion.h>
  20 #include <linux/delay.h>
  21 #include <linux/string.h>
  22 #include <linux/seq_file.h>
  23 #include <linux/platform_device.h>
  24 #include <linux/regulator/consumer.h>
  25 #include <linux/pm_runtime.h>
  26 #include <linux/of.h>
  27 #include <linux/component.h>
  28 
  29 #include <video/omapfb_dss.h>
  30 
  31 #include "dss.h"
  32 #include "dss_features.h"
  33 
  34 /* Venc registers */
  35 #define VENC_REV_ID                             0x00
  36 #define VENC_STATUS                             0x04
  37 #define VENC_F_CONTROL                          0x08
  38 #define VENC_VIDOUT_CTRL                        0x10
  39 #define VENC_SYNC_CTRL                          0x14
  40 #define VENC_LLEN                               0x1C
  41 #define VENC_FLENS                              0x20
  42 #define VENC_HFLTR_CTRL                         0x24
  43 #define VENC_CC_CARR_WSS_CARR                   0x28
  44 #define VENC_C_PHASE                            0x2C
  45 #define VENC_GAIN_U                             0x30
  46 #define VENC_GAIN_V                             0x34
  47 #define VENC_GAIN_Y                             0x38
  48 #define VENC_BLACK_LEVEL                        0x3C
  49 #define VENC_BLANK_LEVEL                        0x40
  50 #define VENC_X_COLOR                            0x44
  51 #define VENC_M_CONTROL                          0x48
  52 #define VENC_BSTAMP_WSS_DATA                    0x4C
  53 #define VENC_S_CARR                             0x50
  54 #define VENC_LINE21                             0x54
  55 #define VENC_LN_SEL                             0x58
  56 #define VENC_L21__WC_CTL                        0x5C
  57 #define VENC_HTRIGGER_VTRIGGER                  0x60
  58 #define VENC_SAVID__EAVID                       0x64
  59 #define VENC_FLEN__FAL                          0x68
  60 #define VENC_LAL__PHASE_RESET                   0x6C
  61 #define VENC_HS_INT_START_STOP_X                0x70
  62 #define VENC_HS_EXT_START_STOP_X                0x74
  63 #define VENC_VS_INT_START_X                     0x78
  64 #define VENC_VS_INT_STOP_X__VS_INT_START_Y      0x7C
  65 #define VENC_VS_INT_STOP_Y__VS_EXT_START_X      0x80
  66 #define VENC_VS_EXT_STOP_X__VS_EXT_START_Y      0x84
  67 #define VENC_VS_EXT_STOP_Y                      0x88
  68 #define VENC_AVID_START_STOP_X                  0x90
  69 #define VENC_AVID_START_STOP_Y                  0x94
  70 #define VENC_FID_INT_START_X__FID_INT_START_Y   0xA0
  71 #define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X  0xA4
  72 #define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y  0xA8
  73 #define VENC_TVDETGP_INT_START_STOP_X           0xB0
  74 #define VENC_TVDETGP_INT_START_STOP_Y           0xB4
  75 #define VENC_GEN_CTRL                           0xB8
  76 #define VENC_OUTPUT_CONTROL                     0xC4
  77 #define VENC_OUTPUT_TEST                        0xC8
  78 #define VENC_DAC_B__DAC_C                       0xC8
  79 
  80 struct venc_config {
  81         u32 f_control;
  82         u32 vidout_ctrl;
  83         u32 sync_ctrl;
  84         u32 llen;
  85         u32 flens;
  86         u32 hfltr_ctrl;
  87         u32 cc_carr_wss_carr;
  88         u32 c_phase;
  89         u32 gain_u;
  90         u32 gain_v;
  91         u32 gain_y;
  92         u32 black_level;
  93         u32 blank_level;
  94         u32 x_color;
  95         u32 m_control;
  96         u32 bstamp_wss_data;
  97         u32 s_carr;
  98         u32 line21;
  99         u32 ln_sel;
 100         u32 l21__wc_ctl;
 101         u32 htrigger_vtrigger;
 102         u32 savid__eavid;
 103         u32 flen__fal;
 104         u32 lal__phase_reset;
 105         u32 hs_int_start_stop_x;
 106         u32 hs_ext_start_stop_x;
 107         u32 vs_int_start_x;
 108         u32 vs_int_stop_x__vs_int_start_y;
 109         u32 vs_int_stop_y__vs_ext_start_x;
 110         u32 vs_ext_stop_x__vs_ext_start_y;
 111         u32 vs_ext_stop_y;
 112         u32 avid_start_stop_x;
 113         u32 avid_start_stop_y;
 114         u32 fid_int_start_x__fid_int_start_y;
 115         u32 fid_int_offset_y__fid_ext_start_x;
 116         u32 fid_ext_start_y__fid_ext_offset_y;
 117         u32 tvdetgp_int_start_stop_x;
 118         u32 tvdetgp_int_start_stop_y;
 119         u32 gen_ctrl;
 120 };
 121 
 122 /* from TRM */
 123 static const struct venc_config venc_config_pal_trm = {
 124         .f_control                              = 0,
 125         .vidout_ctrl                            = 1,
 126         .sync_ctrl                              = 0x40,
 127         .llen                                   = 0x35F, /* 863 */
 128         .flens                                  = 0x270, /* 624 */
 129         .hfltr_ctrl                             = 0,
 130         .cc_carr_wss_carr                       = 0x2F7225ED,
 131         .c_phase                                = 0,
 132         .gain_u                                 = 0x111,
 133         .gain_v                                 = 0x181,
 134         .gain_y                                 = 0x140,
 135         .black_level                            = 0x3B,
 136         .blank_level                            = 0x3B,
 137         .x_color                                = 0x7,
 138         .m_control                              = 0x2,
 139         .bstamp_wss_data                        = 0x3F,
 140         .s_carr                                 = 0x2A098ACB,
 141         .line21                                 = 0,
 142         .ln_sel                                 = 0x01290015,
 143         .l21__wc_ctl                            = 0x0000F603,
 144         .htrigger_vtrigger                      = 0,
 145 
 146         .savid__eavid                           = 0x06A70108,
 147         .flen__fal                              = 0x00180270,
 148         .lal__phase_reset                       = 0x00040135,
 149         .hs_int_start_stop_x                    = 0x00880358,
 150         .hs_ext_start_stop_x                    = 0x000F035F,
 151         .vs_int_start_x                         = 0x01A70000,
 152         .vs_int_stop_x__vs_int_start_y          = 0x000001A7,
 153         .vs_int_stop_y__vs_ext_start_x          = 0x01AF0000,
 154         .vs_ext_stop_x__vs_ext_start_y          = 0x000101AF,
 155         .vs_ext_stop_y                          = 0x00000025,
 156         .avid_start_stop_x                      = 0x03530083,
 157         .avid_start_stop_y                      = 0x026C002E,
 158         .fid_int_start_x__fid_int_start_y       = 0x0001008A,
 159         .fid_int_offset_y__fid_ext_start_x      = 0x002E0138,
 160         .fid_ext_start_y__fid_ext_offset_y      = 0x01380001,
 161 
 162         .tvdetgp_int_start_stop_x               = 0x00140001,
 163         .tvdetgp_int_start_stop_y               = 0x00010001,
 164         .gen_ctrl                               = 0x00FF0000,
 165 };
 166 
 167 /* from TRM */
 168 static const struct venc_config venc_config_ntsc_trm = {
 169         .f_control                              = 0,
 170         .vidout_ctrl                            = 1,
 171         .sync_ctrl                              = 0x8040,
 172         .llen                                   = 0x359,
 173         .flens                                  = 0x20C,
 174         .hfltr_ctrl                             = 0,
 175         .cc_carr_wss_carr                       = 0x043F2631,
 176         .c_phase                                = 0,
 177         .gain_u                                 = 0x102,
 178         .gain_v                                 = 0x16C,
 179         .gain_y                                 = 0x12F,
 180         .black_level                            = 0x43,
 181         .blank_level                            = 0x38,
 182         .x_color                                = 0x7,
 183         .m_control                              = 0x1,
 184         .bstamp_wss_data                        = 0x38,
 185         .s_carr                                 = 0x21F07C1F,
 186         .line21                                 = 0,
 187         .ln_sel                                 = 0x01310011,
 188         .l21__wc_ctl                            = 0x0000F003,
 189         .htrigger_vtrigger                      = 0,
 190 
 191         .savid__eavid                           = 0x069300F4,
 192         .flen__fal                              = 0x0016020C,
 193         .lal__phase_reset                       = 0x00060107,
 194         .hs_int_start_stop_x                    = 0x008E0350,
 195         .hs_ext_start_stop_x                    = 0x000F0359,
 196         .vs_int_start_x                         = 0x01A00000,
 197         .vs_int_stop_x__vs_int_start_y          = 0x020701A0,
 198         .vs_int_stop_y__vs_ext_start_x          = 0x01AC0024,
 199         .vs_ext_stop_x__vs_ext_start_y          = 0x020D01AC,
 200         .vs_ext_stop_y                          = 0x00000006,
 201         .avid_start_stop_x                      = 0x03480078,
 202         .avid_start_stop_y                      = 0x02060024,
 203         .fid_int_start_x__fid_int_start_y       = 0x0001008A,
 204         .fid_int_offset_y__fid_ext_start_x      = 0x01AC0106,
 205         .fid_ext_start_y__fid_ext_offset_y      = 0x01060006,
 206 
 207         .tvdetgp_int_start_stop_x               = 0x00140001,
 208         .tvdetgp_int_start_stop_y               = 0x00010001,
 209         .gen_ctrl                               = 0x00F90000,
 210 };
 211 
 212 static const struct venc_config venc_config_pal_bdghi = {
 213         .f_control                              = 0,
 214         .vidout_ctrl                            = 0,
 215         .sync_ctrl                              = 0,
 216         .hfltr_ctrl                             = 0,
 217         .x_color                                = 0,
 218         .line21                                 = 0,
 219         .ln_sel                                 = 21,
 220         .htrigger_vtrigger                      = 0,
 221         .tvdetgp_int_start_stop_x               = 0x00140001,
 222         .tvdetgp_int_start_stop_y               = 0x00010001,
 223         .gen_ctrl                               = 0x00FB0000,
 224 
 225         .llen                                   = 864-1,
 226         .flens                                  = 625-1,
 227         .cc_carr_wss_carr                       = 0x2F7625ED,
 228         .c_phase                                = 0xDF,
 229         .gain_u                                 = 0x111,
 230         .gain_v                                 = 0x181,
 231         .gain_y                                 = 0x140,
 232         .black_level                            = 0x3e,
 233         .blank_level                            = 0x3e,
 234         .m_control                              = 0<<2 | 1<<1,
 235         .bstamp_wss_data                        = 0x42,
 236         .s_carr                                 = 0x2a098acb,
 237         .l21__wc_ctl                            = 0<<13 | 0x16<<8 | 0<<0,
 238         .savid__eavid                           = 0x06A70108,
 239         .flen__fal                              = 23<<16 | 624<<0,
 240         .lal__phase_reset                       = 2<<17 | 310<<0,
 241         .hs_int_start_stop_x                    = 0x00920358,
 242         .hs_ext_start_stop_x                    = 0x000F035F,
 243         .vs_int_start_x                         = 0x1a7<<16,
 244         .vs_int_stop_x__vs_int_start_y          = 0x000601A7,
 245         .vs_int_stop_y__vs_ext_start_x          = 0x01AF0036,
 246         .vs_ext_stop_x__vs_ext_start_y          = 0x27101af,
 247         .vs_ext_stop_y                          = 0x05,
 248         .avid_start_stop_x                      = 0x03530082,
 249         .avid_start_stop_y                      = 0x0270002E,
 250         .fid_int_start_x__fid_int_start_y       = 0x0005008A,
 251         .fid_int_offset_y__fid_ext_start_x      = 0x002E0138,
 252         .fid_ext_start_y__fid_ext_offset_y      = 0x01380005,
 253 };
 254 
 255 const struct omap_video_timings omap_dss_pal_timings = {
 256         .x_res          = 720,
 257         .y_res          = 574,
 258         .pixelclock     = 13500000,
 259         .hsw            = 64,
 260         .hfp            = 12,
 261         .hbp            = 68,
 262         .vsw            = 5,
 263         .vfp            = 5,
 264         .vbp            = 41,
 265 
 266         .interlace      = true,
 267 };
 268 EXPORT_SYMBOL(omap_dss_pal_timings);
 269 
 270 const struct omap_video_timings omap_dss_ntsc_timings = {
 271         .x_res          = 720,
 272         .y_res          = 482,
 273         .pixelclock     = 13500000,
 274         .hsw            = 64,
 275         .hfp            = 16,
 276         .hbp            = 58,
 277         .vsw            = 6,
 278         .vfp            = 6,
 279         .vbp            = 31,
 280 
 281         .interlace      = true,
 282 };
 283 EXPORT_SYMBOL(omap_dss_ntsc_timings);
 284 
 285 static struct {
 286         struct platform_device *pdev;
 287         void __iomem *base;
 288         struct mutex venc_lock;
 289         u32 wss_data;
 290         struct regulator *vdda_dac_reg;
 291 
 292         struct clk      *tv_dac_clk;
 293 
 294         struct omap_video_timings timings;
 295         enum omap_dss_venc_type type;
 296         bool invert_polarity;
 297 
 298         struct omap_dss_device output;
 299 } venc;
 300 
 301 static inline void venc_write_reg(int idx, u32 val)
 302 {
 303         __raw_writel(val, venc.base + idx);
 304 }
 305 
 306 static inline u32 venc_read_reg(int idx)
 307 {
 308         u32 l = __raw_readl(venc.base + idx);
 309         return l;
 310 }
 311 
 312 static void venc_write_config(const struct venc_config *config)
 313 {
 314         DSSDBG("write venc conf\n");
 315 
 316         venc_write_reg(VENC_LLEN, config->llen);
 317         venc_write_reg(VENC_FLENS, config->flens);
 318         venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
 319         venc_write_reg(VENC_C_PHASE, config->c_phase);
 320         venc_write_reg(VENC_GAIN_U, config->gain_u);
 321         venc_write_reg(VENC_GAIN_V, config->gain_v);
 322         venc_write_reg(VENC_GAIN_Y, config->gain_y);
 323         venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
 324         venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
 325         venc_write_reg(VENC_M_CONTROL, config->m_control);
 326         venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
 327                         venc.wss_data);
 328         venc_write_reg(VENC_S_CARR, config->s_carr);
 329         venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
 330         venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
 331         venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
 332         venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
 333         venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
 334         venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
 335         venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
 336         venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
 337                        config->vs_int_stop_x__vs_int_start_y);
 338         venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
 339                        config->vs_int_stop_y__vs_ext_start_x);
 340         venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
 341                        config->vs_ext_stop_x__vs_ext_start_y);
 342         venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
 343         venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
 344         venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
 345         venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
 346                        config->fid_int_start_x__fid_int_start_y);
 347         venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
 348                        config->fid_int_offset_y__fid_ext_start_x);
 349         venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
 350                        config->fid_ext_start_y__fid_ext_offset_y);
 351 
 352         venc_write_reg(VENC_DAC_B__DAC_C,  venc_read_reg(VENC_DAC_B__DAC_C));
 353         venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
 354         venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
 355         venc_write_reg(VENC_X_COLOR, config->x_color);
 356         venc_write_reg(VENC_LINE21, config->line21);
 357         venc_write_reg(VENC_LN_SEL, config->ln_sel);
 358         venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
 359         venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
 360                        config->tvdetgp_int_start_stop_x);
 361         venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
 362                        config->tvdetgp_int_start_stop_y);
 363         venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
 364         venc_write_reg(VENC_F_CONTROL, config->f_control);
 365         venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
 366 }
 367 
 368 static void venc_reset(void)
 369 {
 370         int t = 1000;
 371 
 372         venc_write_reg(VENC_F_CONTROL, 1<<8);
 373         while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
 374                 if (--t == 0) {
 375                         DSSERR("Failed to reset venc\n");
 376                         return;
 377                 }
 378         }
 379 
 380 #ifdef CONFIG_FB_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
 381         /* the magical sleep that makes things work */
 382         /* XXX more info? What bug this circumvents? */
 383         msleep(20);
 384 #endif
 385 }
 386 
 387 static int venc_runtime_get(void)
 388 {
 389         int r;
 390 
 391         DSSDBG("venc_runtime_get\n");
 392 
 393         r = pm_runtime_get_sync(&venc.pdev->dev);
 394         WARN_ON(r < 0);
 395         return r < 0 ? r : 0;
 396 }
 397 
 398 static void venc_runtime_put(void)
 399 {
 400         int r;
 401 
 402         DSSDBG("venc_runtime_put\n");
 403 
 404         r = pm_runtime_put_sync(&venc.pdev->dev);
 405         WARN_ON(r < 0 && r != -ENOSYS);
 406 }
 407 
 408 static const struct venc_config *venc_timings_to_config(
 409                 struct omap_video_timings *timings)
 410 {
 411         if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
 412                 return &venc_config_pal_trm;
 413 
 414         if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
 415                 return &venc_config_ntsc_trm;
 416 
 417         BUG();
 418         return NULL;
 419 }
 420 
 421 static int venc_power_on(struct omap_dss_device *dssdev)
 422 {
 423         struct omap_overlay_manager *mgr = venc.output.manager;
 424         u32 l;
 425         int r;
 426 
 427         r = venc_runtime_get();
 428         if (r)
 429                 goto err0;
 430 
 431         venc_reset();
 432         venc_write_config(venc_timings_to_config(&venc.timings));
 433 
 434         dss_set_venc_output(venc.type);
 435         dss_set_dac_pwrdn_bgz(1);
 436 
 437         l = 0;
 438 
 439         if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
 440                 l |= 1 << 1;
 441         else /* S-Video */
 442                 l |= (1 << 0) | (1 << 2);
 443 
 444         if (venc.invert_polarity == false)
 445                 l |= 1 << 3;
 446 
 447         venc_write_reg(VENC_OUTPUT_CONTROL, l);
 448 
 449         dss_mgr_set_timings(mgr, &venc.timings);
 450 
 451         r = regulator_enable(venc.vdda_dac_reg);
 452         if (r)
 453                 goto err1;
 454 
 455         r = dss_mgr_enable(mgr);
 456         if (r)
 457                 goto err2;
 458 
 459         return 0;
 460 
 461 err2:
 462         regulator_disable(venc.vdda_dac_reg);
 463 err1:
 464         venc_write_reg(VENC_OUTPUT_CONTROL, 0);
 465         dss_set_dac_pwrdn_bgz(0);
 466 
 467         venc_runtime_put();
 468 err0:
 469         return r;
 470 }
 471 
 472 static void venc_power_off(struct omap_dss_device *dssdev)
 473 {
 474         struct omap_overlay_manager *mgr = venc.output.manager;
 475 
 476         venc_write_reg(VENC_OUTPUT_CONTROL, 0);
 477         dss_set_dac_pwrdn_bgz(0);
 478 
 479         dss_mgr_disable(mgr);
 480 
 481         regulator_disable(venc.vdda_dac_reg);
 482 
 483         venc_runtime_put();
 484 }
 485 
 486 static int venc_display_enable(struct omap_dss_device *dssdev)
 487 {
 488         struct omap_dss_device *out = &venc.output;
 489         int r;
 490 
 491         DSSDBG("venc_display_enable\n");
 492 
 493         mutex_lock(&venc.venc_lock);
 494 
 495         if (out->manager == NULL) {
 496                 DSSERR("Failed to enable display: no output/manager\n");
 497                 r = -ENODEV;
 498                 goto err0;
 499         }
 500 
 501         r = venc_power_on(dssdev);
 502         if (r)
 503                 goto err0;
 504 
 505         venc.wss_data = 0;
 506 
 507         mutex_unlock(&venc.venc_lock);
 508 
 509         return 0;
 510 err0:
 511         mutex_unlock(&venc.venc_lock);
 512         return r;
 513 }
 514 
 515 static void venc_display_disable(struct omap_dss_device *dssdev)
 516 {
 517         DSSDBG("venc_display_disable\n");
 518 
 519         mutex_lock(&venc.venc_lock);
 520 
 521         venc_power_off(dssdev);
 522 
 523         mutex_unlock(&venc.venc_lock);
 524 }
 525 
 526 static void venc_set_timings(struct omap_dss_device *dssdev,
 527                 struct omap_video_timings *timings)
 528 {
 529         DSSDBG("venc_set_timings\n");
 530 
 531         mutex_lock(&venc.venc_lock);
 532 
 533         /* Reset WSS data when the TV standard changes. */
 534         if (memcmp(&venc.timings, timings, sizeof(*timings)))
 535                 venc.wss_data = 0;
 536 
 537         venc.timings = *timings;
 538 
 539         dispc_set_tv_pclk(13500000);
 540 
 541         mutex_unlock(&venc.venc_lock);
 542 }
 543 
 544 static int venc_check_timings(struct omap_dss_device *dssdev,
 545                 struct omap_video_timings *timings)
 546 {
 547         DSSDBG("venc_check_timings\n");
 548 
 549         if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
 550                 return 0;
 551 
 552         if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
 553                 return 0;
 554 
 555         return -EINVAL;
 556 }
 557 
 558 static void venc_get_timings(struct omap_dss_device *dssdev,
 559                 struct omap_video_timings *timings)
 560 {
 561         mutex_lock(&venc.venc_lock);
 562 
 563         *timings = venc.timings;
 564 
 565         mutex_unlock(&venc.venc_lock);
 566 }
 567 
 568 static u32 venc_get_wss(struct omap_dss_device *dssdev)
 569 {
 570         /* Invert due to VENC_L21_WC_CTL:INV=1 */
 571         return (venc.wss_data >> 8) ^ 0xfffff;
 572 }
 573 
 574 static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
 575 {
 576         const struct venc_config *config;
 577         int r;
 578 
 579         DSSDBG("venc_set_wss\n");
 580 
 581         mutex_lock(&venc.venc_lock);
 582 
 583         config = venc_timings_to_config(&venc.timings);
 584 
 585         /* Invert due to VENC_L21_WC_CTL:INV=1 */
 586         venc.wss_data = (wss ^ 0xfffff) << 8;
 587 
 588         r = venc_runtime_get();
 589         if (r)
 590                 goto err;
 591 
 592         venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
 593                         venc.wss_data);
 594 
 595         venc_runtime_put();
 596 
 597 err:
 598         mutex_unlock(&venc.venc_lock);
 599 
 600         return r;
 601 }
 602 
 603 static void venc_set_type(struct omap_dss_device *dssdev,
 604                 enum omap_dss_venc_type type)
 605 {
 606         mutex_lock(&venc.venc_lock);
 607 
 608         venc.type = type;
 609 
 610         mutex_unlock(&venc.venc_lock);
 611 }
 612 
 613 static void venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
 614                 bool invert_polarity)
 615 {
 616         mutex_lock(&venc.venc_lock);
 617 
 618         venc.invert_polarity = invert_polarity;
 619 
 620         mutex_unlock(&venc.venc_lock);
 621 }
 622 
 623 static int venc_init_regulator(void)
 624 {
 625         struct regulator *vdda_dac;
 626 
 627         if (venc.vdda_dac_reg != NULL)
 628                 return 0;
 629 
 630         if (venc.pdev->dev.of_node)
 631                 vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda");
 632         else
 633                 vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac");
 634 
 635         if (IS_ERR(vdda_dac)) {
 636                 if (PTR_ERR(vdda_dac) != -EPROBE_DEFER)
 637                         DSSERR("can't get VDDA_DAC regulator\n");
 638                 return PTR_ERR(vdda_dac);
 639         }
 640 
 641         venc.vdda_dac_reg = vdda_dac;
 642 
 643         return 0;
 644 }
 645 
 646 static void venc_dump_regs(struct seq_file *s)
 647 {
 648 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
 649 
 650         if (venc_runtime_get())
 651                 return;
 652 
 653         DUMPREG(VENC_F_CONTROL);
 654         DUMPREG(VENC_VIDOUT_CTRL);
 655         DUMPREG(VENC_SYNC_CTRL);
 656         DUMPREG(VENC_LLEN);
 657         DUMPREG(VENC_FLENS);
 658         DUMPREG(VENC_HFLTR_CTRL);
 659         DUMPREG(VENC_CC_CARR_WSS_CARR);
 660         DUMPREG(VENC_C_PHASE);
 661         DUMPREG(VENC_GAIN_U);
 662         DUMPREG(VENC_GAIN_V);
 663         DUMPREG(VENC_GAIN_Y);
 664         DUMPREG(VENC_BLACK_LEVEL);
 665         DUMPREG(VENC_BLANK_LEVEL);
 666         DUMPREG(VENC_X_COLOR);
 667         DUMPREG(VENC_M_CONTROL);
 668         DUMPREG(VENC_BSTAMP_WSS_DATA);
 669         DUMPREG(VENC_S_CARR);
 670         DUMPREG(VENC_LINE21);
 671         DUMPREG(VENC_LN_SEL);
 672         DUMPREG(VENC_L21__WC_CTL);
 673         DUMPREG(VENC_HTRIGGER_VTRIGGER);
 674         DUMPREG(VENC_SAVID__EAVID);
 675         DUMPREG(VENC_FLEN__FAL);
 676         DUMPREG(VENC_LAL__PHASE_RESET);
 677         DUMPREG(VENC_HS_INT_START_STOP_X);
 678         DUMPREG(VENC_HS_EXT_START_STOP_X);
 679         DUMPREG(VENC_VS_INT_START_X);
 680         DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
 681         DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
 682         DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
 683         DUMPREG(VENC_VS_EXT_STOP_Y);
 684         DUMPREG(VENC_AVID_START_STOP_X);
 685         DUMPREG(VENC_AVID_START_STOP_Y);
 686         DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
 687         DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
 688         DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
 689         DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
 690         DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
 691         DUMPREG(VENC_GEN_CTRL);
 692         DUMPREG(VENC_OUTPUT_CONTROL);
 693         DUMPREG(VENC_OUTPUT_TEST);
 694 
 695         venc_runtime_put();
 696 
 697 #undef DUMPREG
 698 }
 699 
 700 static int venc_get_clocks(struct platform_device *pdev)
 701 {
 702         struct clk *clk;
 703 
 704         if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
 705                 clk = devm_clk_get(&pdev->dev, "tv_dac_clk");
 706                 if (IS_ERR(clk)) {
 707                         DSSERR("can't get tv_dac_clk\n");
 708                         return PTR_ERR(clk);
 709                 }
 710         } else {
 711                 clk = NULL;
 712         }
 713 
 714         venc.tv_dac_clk = clk;
 715 
 716         return 0;
 717 }
 718 
 719 static int venc_connect(struct omap_dss_device *dssdev,
 720                 struct omap_dss_device *dst)
 721 {
 722         struct omap_overlay_manager *mgr;
 723         int r;
 724 
 725         r = venc_init_regulator();
 726         if (r)
 727                 return r;
 728 
 729         mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
 730         if (!mgr)
 731                 return -ENODEV;
 732 
 733         r = dss_mgr_connect(mgr, dssdev);
 734         if (r)
 735                 return r;
 736 
 737         r = omapdss_output_set_device(dssdev, dst);
 738         if (r) {
 739                 DSSERR("failed to connect output to new device: %s\n",
 740                                 dst->name);
 741                 dss_mgr_disconnect(mgr, dssdev);
 742                 return r;
 743         }
 744 
 745         return 0;
 746 }
 747 
 748 static void venc_disconnect(struct omap_dss_device *dssdev,
 749                 struct omap_dss_device *dst)
 750 {
 751         WARN_ON(dst != dssdev->dst);
 752 
 753         if (dst != dssdev->dst)
 754                 return;
 755 
 756         omapdss_output_unset_device(dssdev);
 757 
 758         if (dssdev->manager)
 759                 dss_mgr_disconnect(dssdev->manager, dssdev);
 760 }
 761 
 762 static const struct omapdss_atv_ops venc_ops = {
 763         .connect = venc_connect,
 764         .disconnect = venc_disconnect,
 765 
 766         .enable = venc_display_enable,
 767         .disable = venc_display_disable,
 768 
 769         .check_timings = venc_check_timings,
 770         .set_timings = venc_set_timings,
 771         .get_timings = venc_get_timings,
 772 
 773         .set_type = venc_set_type,
 774         .invert_vid_out_polarity = venc_invert_vid_out_polarity,
 775 
 776         .set_wss = venc_set_wss,
 777         .get_wss = venc_get_wss,
 778 };
 779 
 780 static void venc_init_output(struct platform_device *pdev)
 781 {
 782         struct omap_dss_device *out = &venc.output;
 783 
 784         out->dev = &pdev->dev;
 785         out->id = OMAP_DSS_OUTPUT_VENC;
 786         out->output_type = OMAP_DISPLAY_TYPE_VENC;
 787         out->name = "venc.0";
 788         out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
 789         out->ops.atv = &venc_ops;
 790         out->owner = THIS_MODULE;
 791 
 792         omapdss_register_output(out);
 793 }
 794 
 795 static void venc_uninit_output(struct platform_device *pdev)
 796 {
 797         struct omap_dss_device *out = &venc.output;
 798 
 799         omapdss_unregister_output(out);
 800 }
 801 
 802 static int venc_probe_of(struct platform_device *pdev)
 803 {
 804         struct device_node *node = pdev->dev.of_node;
 805         struct device_node *ep;
 806         u32 channels;
 807         int r;
 808 
 809         ep = omapdss_of_get_first_endpoint(node);
 810         if (!ep)
 811                 return 0;
 812 
 813         venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity");
 814 
 815         r = of_property_read_u32(ep, "ti,channels", &channels);
 816         if (r) {
 817                 dev_err(&pdev->dev,
 818                         "failed to read property 'ti,channels': %d\n", r);
 819                 goto err;
 820         }
 821 
 822         switch (channels) {
 823         case 1:
 824                 venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
 825                 break;
 826         case 2:
 827                 venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
 828                 break;
 829         default:
 830                 dev_err(&pdev->dev, "bad channel propert '%d'\n", channels);
 831                 r = -EINVAL;
 832                 goto err;
 833         }
 834 
 835         of_node_put(ep);
 836 
 837         return 0;
 838 err:
 839         of_node_put(ep);
 840 
 841         return 0;
 842 }
 843 
 844 /* VENC HW IP initialisation */
 845 static int venc_bind(struct device *dev, struct device *master, void *data)
 846 {
 847         struct platform_device *pdev = to_platform_device(dev);
 848         u8 rev_id;
 849         struct resource *venc_mem;
 850         int r;
 851 
 852         venc.pdev = pdev;
 853 
 854         mutex_init(&venc.venc_lock);
 855 
 856         venc.wss_data = 0;
 857 
 858         venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
 859         if (!venc_mem) {
 860                 DSSERR("can't get IORESOURCE_MEM VENC\n");
 861                 return -EINVAL;
 862         }
 863 
 864         venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
 865                                  resource_size(venc_mem));
 866         if (!venc.base) {
 867                 DSSERR("can't ioremap VENC\n");
 868                 return -ENOMEM;
 869         }
 870 
 871         r = venc_get_clocks(pdev);
 872         if (r)
 873                 return r;
 874 
 875         pm_runtime_enable(&pdev->dev);
 876 
 877         r = venc_runtime_get();
 878         if (r)
 879                 goto err_runtime_get;
 880 
 881         rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
 882         dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
 883 
 884         venc_runtime_put();
 885 
 886         if (pdev->dev.of_node) {
 887                 r = venc_probe_of(pdev);
 888                 if (r) {
 889                         DSSERR("Invalid DT data\n");
 890                         goto err_probe_of;
 891                 }
 892         }
 893 
 894         dss_debugfs_create_file("venc", venc_dump_regs);
 895 
 896         venc_init_output(pdev);
 897 
 898         return 0;
 899 
 900 err_probe_of:
 901 err_runtime_get:
 902         pm_runtime_disable(&pdev->dev);
 903         return r;
 904 }
 905 
 906 static void venc_unbind(struct device *dev, struct device *master, void *data)
 907 {
 908         struct platform_device *pdev = to_platform_device(dev);
 909 
 910         venc_uninit_output(pdev);
 911 
 912         pm_runtime_disable(&pdev->dev);
 913 }
 914 
 915 static const struct component_ops venc_component_ops = {
 916         .bind   = venc_bind,
 917         .unbind = venc_unbind,
 918 };
 919 
 920 static int venc_probe(struct platform_device *pdev)
 921 {
 922         return component_add(&pdev->dev, &venc_component_ops);
 923 }
 924 
 925 static int venc_remove(struct platform_device *pdev)
 926 {
 927         component_del(&pdev->dev, &venc_component_ops);
 928         return 0;
 929 }
 930 
 931 static int venc_runtime_suspend(struct device *dev)
 932 {
 933         if (venc.tv_dac_clk)
 934                 clk_disable_unprepare(venc.tv_dac_clk);
 935 
 936         dispc_runtime_put();
 937 
 938         return 0;
 939 }
 940 
 941 static int venc_runtime_resume(struct device *dev)
 942 {
 943         int r;
 944 
 945         r = dispc_runtime_get();
 946         if (r < 0)
 947                 return r;
 948 
 949         if (venc.tv_dac_clk)
 950                 clk_prepare_enable(venc.tv_dac_clk);
 951 
 952         return 0;
 953 }
 954 
 955 static const struct dev_pm_ops venc_pm_ops = {
 956         .runtime_suspend = venc_runtime_suspend,
 957         .runtime_resume = venc_runtime_resume,
 958 };
 959 
 960 static const struct of_device_id venc_of_match[] = {
 961         { .compatible = "ti,omap2-venc", },
 962         { .compatible = "ti,omap3-venc", },
 963         { .compatible = "ti,omap4-venc", },
 964         {},
 965 };
 966 
 967 static struct platform_driver omap_venchw_driver = {
 968         .probe          = venc_probe,
 969         .remove         = venc_remove,
 970         .driver         = {
 971                 .name   = "omapdss_venc",
 972                 .pm     = &venc_pm_ops,
 973                 .of_match_table = venc_of_match,
 974                 .suppress_bind_attrs = true,
 975         },
 976 };
 977 
 978 int __init venc_init_platform_driver(void)
 979 {
 980         return platform_driver_register(&omap_venchw_driver);
 981 }
 982 
 983 void venc_uninit_platform_driver(void)
 984 {
 985         platform_driver_unregister(&omap_venchw_driver);
 986 }

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