cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

venc.c (23173B)


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