18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/drivers/video/omap2/dss/venc.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Nokia Corporation 68c2ecf20Sopenharmony_ci * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * VENC settings from TI's DSS driver 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define DSS_SUBSYS_NAME "VENC" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/clk.h> 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci#include <linux/io.h> 188c2ecf20Sopenharmony_ci#include <linux/mutex.h> 198c2ecf20Sopenharmony_ci#include <linux/completion.h> 208c2ecf20Sopenharmony_ci#include <linux/delay.h> 218c2ecf20Sopenharmony_ci#include <linux/string.h> 228c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 238c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 248c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 258c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 268c2ecf20Sopenharmony_ci#include <linux/of.h> 278c2ecf20Sopenharmony_ci#include <linux/component.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <video/omapfb_dss.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include "dss.h" 328c2ecf20Sopenharmony_ci#include "dss_features.h" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* Venc registers */ 358c2ecf20Sopenharmony_ci#define VENC_REV_ID 0x00 368c2ecf20Sopenharmony_ci#define VENC_STATUS 0x04 378c2ecf20Sopenharmony_ci#define VENC_F_CONTROL 0x08 388c2ecf20Sopenharmony_ci#define VENC_VIDOUT_CTRL 0x10 398c2ecf20Sopenharmony_ci#define VENC_SYNC_CTRL 0x14 408c2ecf20Sopenharmony_ci#define VENC_LLEN 0x1C 418c2ecf20Sopenharmony_ci#define VENC_FLENS 0x20 428c2ecf20Sopenharmony_ci#define VENC_HFLTR_CTRL 0x24 438c2ecf20Sopenharmony_ci#define VENC_CC_CARR_WSS_CARR 0x28 448c2ecf20Sopenharmony_ci#define VENC_C_PHASE 0x2C 458c2ecf20Sopenharmony_ci#define VENC_GAIN_U 0x30 468c2ecf20Sopenharmony_ci#define VENC_GAIN_V 0x34 478c2ecf20Sopenharmony_ci#define VENC_GAIN_Y 0x38 488c2ecf20Sopenharmony_ci#define VENC_BLACK_LEVEL 0x3C 498c2ecf20Sopenharmony_ci#define VENC_BLANK_LEVEL 0x40 508c2ecf20Sopenharmony_ci#define VENC_X_COLOR 0x44 518c2ecf20Sopenharmony_ci#define VENC_M_CONTROL 0x48 528c2ecf20Sopenharmony_ci#define VENC_BSTAMP_WSS_DATA 0x4C 538c2ecf20Sopenharmony_ci#define VENC_S_CARR 0x50 548c2ecf20Sopenharmony_ci#define VENC_LINE21 0x54 558c2ecf20Sopenharmony_ci#define VENC_LN_SEL 0x58 568c2ecf20Sopenharmony_ci#define VENC_L21__WC_CTL 0x5C 578c2ecf20Sopenharmony_ci#define VENC_HTRIGGER_VTRIGGER 0x60 588c2ecf20Sopenharmony_ci#define VENC_SAVID__EAVID 0x64 598c2ecf20Sopenharmony_ci#define VENC_FLEN__FAL 0x68 608c2ecf20Sopenharmony_ci#define VENC_LAL__PHASE_RESET 0x6C 618c2ecf20Sopenharmony_ci#define VENC_HS_INT_START_STOP_X 0x70 628c2ecf20Sopenharmony_ci#define VENC_HS_EXT_START_STOP_X 0x74 638c2ecf20Sopenharmony_ci#define VENC_VS_INT_START_X 0x78 648c2ecf20Sopenharmony_ci#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C 658c2ecf20Sopenharmony_ci#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80 668c2ecf20Sopenharmony_ci#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84 678c2ecf20Sopenharmony_ci#define VENC_VS_EXT_STOP_Y 0x88 688c2ecf20Sopenharmony_ci#define VENC_AVID_START_STOP_X 0x90 698c2ecf20Sopenharmony_ci#define VENC_AVID_START_STOP_Y 0x94 708c2ecf20Sopenharmony_ci#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0 718c2ecf20Sopenharmony_ci#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4 728c2ecf20Sopenharmony_ci#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8 738c2ecf20Sopenharmony_ci#define VENC_TVDETGP_INT_START_STOP_X 0xB0 748c2ecf20Sopenharmony_ci#define VENC_TVDETGP_INT_START_STOP_Y 0xB4 758c2ecf20Sopenharmony_ci#define VENC_GEN_CTRL 0xB8 768c2ecf20Sopenharmony_ci#define VENC_OUTPUT_CONTROL 0xC4 778c2ecf20Sopenharmony_ci#define VENC_OUTPUT_TEST 0xC8 788c2ecf20Sopenharmony_ci#define VENC_DAC_B__DAC_C 0xC8 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct venc_config { 818c2ecf20Sopenharmony_ci u32 f_control; 828c2ecf20Sopenharmony_ci u32 vidout_ctrl; 838c2ecf20Sopenharmony_ci u32 sync_ctrl; 848c2ecf20Sopenharmony_ci u32 llen; 858c2ecf20Sopenharmony_ci u32 flens; 868c2ecf20Sopenharmony_ci u32 hfltr_ctrl; 878c2ecf20Sopenharmony_ci u32 cc_carr_wss_carr; 888c2ecf20Sopenharmony_ci u32 c_phase; 898c2ecf20Sopenharmony_ci u32 gain_u; 908c2ecf20Sopenharmony_ci u32 gain_v; 918c2ecf20Sopenharmony_ci u32 gain_y; 928c2ecf20Sopenharmony_ci u32 black_level; 938c2ecf20Sopenharmony_ci u32 blank_level; 948c2ecf20Sopenharmony_ci u32 x_color; 958c2ecf20Sopenharmony_ci u32 m_control; 968c2ecf20Sopenharmony_ci u32 bstamp_wss_data; 978c2ecf20Sopenharmony_ci u32 s_carr; 988c2ecf20Sopenharmony_ci u32 line21; 998c2ecf20Sopenharmony_ci u32 ln_sel; 1008c2ecf20Sopenharmony_ci u32 l21__wc_ctl; 1018c2ecf20Sopenharmony_ci u32 htrigger_vtrigger; 1028c2ecf20Sopenharmony_ci u32 savid__eavid; 1038c2ecf20Sopenharmony_ci u32 flen__fal; 1048c2ecf20Sopenharmony_ci u32 lal__phase_reset; 1058c2ecf20Sopenharmony_ci u32 hs_int_start_stop_x; 1068c2ecf20Sopenharmony_ci u32 hs_ext_start_stop_x; 1078c2ecf20Sopenharmony_ci u32 vs_int_start_x; 1088c2ecf20Sopenharmony_ci u32 vs_int_stop_x__vs_int_start_y; 1098c2ecf20Sopenharmony_ci u32 vs_int_stop_y__vs_ext_start_x; 1108c2ecf20Sopenharmony_ci u32 vs_ext_stop_x__vs_ext_start_y; 1118c2ecf20Sopenharmony_ci u32 vs_ext_stop_y; 1128c2ecf20Sopenharmony_ci u32 avid_start_stop_x; 1138c2ecf20Sopenharmony_ci u32 avid_start_stop_y; 1148c2ecf20Sopenharmony_ci u32 fid_int_start_x__fid_int_start_y; 1158c2ecf20Sopenharmony_ci u32 fid_int_offset_y__fid_ext_start_x; 1168c2ecf20Sopenharmony_ci u32 fid_ext_start_y__fid_ext_offset_y; 1178c2ecf20Sopenharmony_ci u32 tvdetgp_int_start_stop_x; 1188c2ecf20Sopenharmony_ci u32 tvdetgp_int_start_stop_y; 1198c2ecf20Sopenharmony_ci u32 gen_ctrl; 1208c2ecf20Sopenharmony_ci}; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/* from TRM */ 1238c2ecf20Sopenharmony_cistatic const struct venc_config venc_config_pal_trm = { 1248c2ecf20Sopenharmony_ci .f_control = 0, 1258c2ecf20Sopenharmony_ci .vidout_ctrl = 1, 1268c2ecf20Sopenharmony_ci .sync_ctrl = 0x40, 1278c2ecf20Sopenharmony_ci .llen = 0x35F, /* 863 */ 1288c2ecf20Sopenharmony_ci .flens = 0x270, /* 624 */ 1298c2ecf20Sopenharmony_ci .hfltr_ctrl = 0, 1308c2ecf20Sopenharmony_ci .cc_carr_wss_carr = 0x2F7225ED, 1318c2ecf20Sopenharmony_ci .c_phase = 0, 1328c2ecf20Sopenharmony_ci .gain_u = 0x111, 1338c2ecf20Sopenharmony_ci .gain_v = 0x181, 1348c2ecf20Sopenharmony_ci .gain_y = 0x140, 1358c2ecf20Sopenharmony_ci .black_level = 0x3B, 1368c2ecf20Sopenharmony_ci .blank_level = 0x3B, 1378c2ecf20Sopenharmony_ci .x_color = 0x7, 1388c2ecf20Sopenharmony_ci .m_control = 0x2, 1398c2ecf20Sopenharmony_ci .bstamp_wss_data = 0x3F, 1408c2ecf20Sopenharmony_ci .s_carr = 0x2A098ACB, 1418c2ecf20Sopenharmony_ci .line21 = 0, 1428c2ecf20Sopenharmony_ci .ln_sel = 0x01290015, 1438c2ecf20Sopenharmony_ci .l21__wc_ctl = 0x0000F603, 1448c2ecf20Sopenharmony_ci .htrigger_vtrigger = 0, 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci .savid__eavid = 0x06A70108, 1478c2ecf20Sopenharmony_ci .flen__fal = 0x00180270, 1488c2ecf20Sopenharmony_ci .lal__phase_reset = 0x00040135, 1498c2ecf20Sopenharmony_ci .hs_int_start_stop_x = 0x00880358, 1508c2ecf20Sopenharmony_ci .hs_ext_start_stop_x = 0x000F035F, 1518c2ecf20Sopenharmony_ci .vs_int_start_x = 0x01A70000, 1528c2ecf20Sopenharmony_ci .vs_int_stop_x__vs_int_start_y = 0x000001A7, 1538c2ecf20Sopenharmony_ci .vs_int_stop_y__vs_ext_start_x = 0x01AF0000, 1548c2ecf20Sopenharmony_ci .vs_ext_stop_x__vs_ext_start_y = 0x000101AF, 1558c2ecf20Sopenharmony_ci .vs_ext_stop_y = 0x00000025, 1568c2ecf20Sopenharmony_ci .avid_start_stop_x = 0x03530083, 1578c2ecf20Sopenharmony_ci .avid_start_stop_y = 0x026C002E, 1588c2ecf20Sopenharmony_ci .fid_int_start_x__fid_int_start_y = 0x0001008A, 1598c2ecf20Sopenharmony_ci .fid_int_offset_y__fid_ext_start_x = 0x002E0138, 1608c2ecf20Sopenharmony_ci .fid_ext_start_y__fid_ext_offset_y = 0x01380001, 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci .tvdetgp_int_start_stop_x = 0x00140001, 1638c2ecf20Sopenharmony_ci .tvdetgp_int_start_stop_y = 0x00010001, 1648c2ecf20Sopenharmony_ci .gen_ctrl = 0x00FF0000, 1658c2ecf20Sopenharmony_ci}; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* from TRM */ 1688c2ecf20Sopenharmony_cistatic const struct venc_config venc_config_ntsc_trm = { 1698c2ecf20Sopenharmony_ci .f_control = 0, 1708c2ecf20Sopenharmony_ci .vidout_ctrl = 1, 1718c2ecf20Sopenharmony_ci .sync_ctrl = 0x8040, 1728c2ecf20Sopenharmony_ci .llen = 0x359, 1738c2ecf20Sopenharmony_ci .flens = 0x20C, 1748c2ecf20Sopenharmony_ci .hfltr_ctrl = 0, 1758c2ecf20Sopenharmony_ci .cc_carr_wss_carr = 0x043F2631, 1768c2ecf20Sopenharmony_ci .c_phase = 0, 1778c2ecf20Sopenharmony_ci .gain_u = 0x102, 1788c2ecf20Sopenharmony_ci .gain_v = 0x16C, 1798c2ecf20Sopenharmony_ci .gain_y = 0x12F, 1808c2ecf20Sopenharmony_ci .black_level = 0x43, 1818c2ecf20Sopenharmony_ci .blank_level = 0x38, 1828c2ecf20Sopenharmony_ci .x_color = 0x7, 1838c2ecf20Sopenharmony_ci .m_control = 0x1, 1848c2ecf20Sopenharmony_ci .bstamp_wss_data = 0x38, 1858c2ecf20Sopenharmony_ci .s_carr = 0x21F07C1F, 1868c2ecf20Sopenharmony_ci .line21 = 0, 1878c2ecf20Sopenharmony_ci .ln_sel = 0x01310011, 1888c2ecf20Sopenharmony_ci .l21__wc_ctl = 0x0000F003, 1898c2ecf20Sopenharmony_ci .htrigger_vtrigger = 0, 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci .savid__eavid = 0x069300F4, 1928c2ecf20Sopenharmony_ci .flen__fal = 0x0016020C, 1938c2ecf20Sopenharmony_ci .lal__phase_reset = 0x00060107, 1948c2ecf20Sopenharmony_ci .hs_int_start_stop_x = 0x008E0350, 1958c2ecf20Sopenharmony_ci .hs_ext_start_stop_x = 0x000F0359, 1968c2ecf20Sopenharmony_ci .vs_int_start_x = 0x01A00000, 1978c2ecf20Sopenharmony_ci .vs_int_stop_x__vs_int_start_y = 0x020701A0, 1988c2ecf20Sopenharmony_ci .vs_int_stop_y__vs_ext_start_x = 0x01AC0024, 1998c2ecf20Sopenharmony_ci .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC, 2008c2ecf20Sopenharmony_ci .vs_ext_stop_y = 0x00000006, 2018c2ecf20Sopenharmony_ci .avid_start_stop_x = 0x03480078, 2028c2ecf20Sopenharmony_ci .avid_start_stop_y = 0x02060024, 2038c2ecf20Sopenharmony_ci .fid_int_start_x__fid_int_start_y = 0x0001008A, 2048c2ecf20Sopenharmony_ci .fid_int_offset_y__fid_ext_start_x = 0x01AC0106, 2058c2ecf20Sopenharmony_ci .fid_ext_start_y__fid_ext_offset_y = 0x01060006, 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci .tvdetgp_int_start_stop_x = 0x00140001, 2088c2ecf20Sopenharmony_ci .tvdetgp_int_start_stop_y = 0x00010001, 2098c2ecf20Sopenharmony_ci .gen_ctrl = 0x00F90000, 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ciconst struct omap_video_timings omap_dss_pal_timings = { 2138c2ecf20Sopenharmony_ci .x_res = 720, 2148c2ecf20Sopenharmony_ci .y_res = 574, 2158c2ecf20Sopenharmony_ci .pixelclock = 13500000, 2168c2ecf20Sopenharmony_ci .hsw = 64, 2178c2ecf20Sopenharmony_ci .hfp = 12, 2188c2ecf20Sopenharmony_ci .hbp = 68, 2198c2ecf20Sopenharmony_ci .vsw = 5, 2208c2ecf20Sopenharmony_ci .vfp = 5, 2218c2ecf20Sopenharmony_ci .vbp = 41, 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci .interlace = true, 2248c2ecf20Sopenharmony_ci}; 2258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(omap_dss_pal_timings); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciconst struct omap_video_timings omap_dss_ntsc_timings = { 2288c2ecf20Sopenharmony_ci .x_res = 720, 2298c2ecf20Sopenharmony_ci .y_res = 482, 2308c2ecf20Sopenharmony_ci .pixelclock = 13500000, 2318c2ecf20Sopenharmony_ci .hsw = 64, 2328c2ecf20Sopenharmony_ci .hfp = 16, 2338c2ecf20Sopenharmony_ci .hbp = 58, 2348c2ecf20Sopenharmony_ci .vsw = 6, 2358c2ecf20Sopenharmony_ci .vfp = 6, 2368c2ecf20Sopenharmony_ci .vbp = 31, 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci .interlace = true, 2398c2ecf20Sopenharmony_ci}; 2408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(omap_dss_ntsc_timings); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic struct { 2438c2ecf20Sopenharmony_ci struct platform_device *pdev; 2448c2ecf20Sopenharmony_ci void __iomem *base; 2458c2ecf20Sopenharmony_ci struct mutex venc_lock; 2468c2ecf20Sopenharmony_ci u32 wss_data; 2478c2ecf20Sopenharmony_ci struct regulator *vdda_dac_reg; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci struct clk *tv_dac_clk; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci struct omap_video_timings timings; 2528c2ecf20Sopenharmony_ci enum omap_dss_venc_type type; 2538c2ecf20Sopenharmony_ci bool invert_polarity; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci struct omap_dss_device output; 2568c2ecf20Sopenharmony_ci} venc; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic inline void venc_write_reg(int idx, u32 val) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci __raw_writel(val, venc.base + idx); 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic inline u32 venc_read_reg(int idx) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci u32 l = __raw_readl(venc.base + idx); 2668c2ecf20Sopenharmony_ci return l; 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic void venc_write_config(const struct venc_config *config) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci DSSDBG("write venc conf\n"); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci venc_write_reg(VENC_LLEN, config->llen); 2748c2ecf20Sopenharmony_ci venc_write_reg(VENC_FLENS, config->flens); 2758c2ecf20Sopenharmony_ci venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr); 2768c2ecf20Sopenharmony_ci venc_write_reg(VENC_C_PHASE, config->c_phase); 2778c2ecf20Sopenharmony_ci venc_write_reg(VENC_GAIN_U, config->gain_u); 2788c2ecf20Sopenharmony_ci venc_write_reg(VENC_GAIN_V, config->gain_v); 2798c2ecf20Sopenharmony_ci venc_write_reg(VENC_GAIN_Y, config->gain_y); 2808c2ecf20Sopenharmony_ci venc_write_reg(VENC_BLACK_LEVEL, config->black_level); 2818c2ecf20Sopenharmony_ci venc_write_reg(VENC_BLANK_LEVEL, config->blank_level); 2828c2ecf20Sopenharmony_ci venc_write_reg(VENC_M_CONTROL, config->m_control); 2838c2ecf20Sopenharmony_ci venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | 2848c2ecf20Sopenharmony_ci venc.wss_data); 2858c2ecf20Sopenharmony_ci venc_write_reg(VENC_S_CARR, config->s_carr); 2868c2ecf20Sopenharmony_ci venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl); 2878c2ecf20Sopenharmony_ci venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid); 2888c2ecf20Sopenharmony_ci venc_write_reg(VENC_FLEN__FAL, config->flen__fal); 2898c2ecf20Sopenharmony_ci venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset); 2908c2ecf20Sopenharmony_ci venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x); 2918c2ecf20Sopenharmony_ci venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x); 2928c2ecf20Sopenharmony_ci venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x); 2938c2ecf20Sopenharmony_ci venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y, 2948c2ecf20Sopenharmony_ci config->vs_int_stop_x__vs_int_start_y); 2958c2ecf20Sopenharmony_ci venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X, 2968c2ecf20Sopenharmony_ci config->vs_int_stop_y__vs_ext_start_x); 2978c2ecf20Sopenharmony_ci venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y, 2988c2ecf20Sopenharmony_ci config->vs_ext_stop_x__vs_ext_start_y); 2998c2ecf20Sopenharmony_ci venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y); 3008c2ecf20Sopenharmony_ci venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x); 3018c2ecf20Sopenharmony_ci venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y); 3028c2ecf20Sopenharmony_ci venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y, 3038c2ecf20Sopenharmony_ci config->fid_int_start_x__fid_int_start_y); 3048c2ecf20Sopenharmony_ci venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X, 3058c2ecf20Sopenharmony_ci config->fid_int_offset_y__fid_ext_start_x); 3068c2ecf20Sopenharmony_ci venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y, 3078c2ecf20Sopenharmony_ci config->fid_ext_start_y__fid_ext_offset_y); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C)); 3108c2ecf20Sopenharmony_ci venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl); 3118c2ecf20Sopenharmony_ci venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl); 3128c2ecf20Sopenharmony_ci venc_write_reg(VENC_X_COLOR, config->x_color); 3138c2ecf20Sopenharmony_ci venc_write_reg(VENC_LINE21, config->line21); 3148c2ecf20Sopenharmony_ci venc_write_reg(VENC_LN_SEL, config->ln_sel); 3158c2ecf20Sopenharmony_ci venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger); 3168c2ecf20Sopenharmony_ci venc_write_reg(VENC_TVDETGP_INT_START_STOP_X, 3178c2ecf20Sopenharmony_ci config->tvdetgp_int_start_stop_x); 3188c2ecf20Sopenharmony_ci venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y, 3198c2ecf20Sopenharmony_ci config->tvdetgp_int_start_stop_y); 3208c2ecf20Sopenharmony_ci venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl); 3218c2ecf20Sopenharmony_ci venc_write_reg(VENC_F_CONTROL, config->f_control); 3228c2ecf20Sopenharmony_ci venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl); 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic void venc_reset(void) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci int t = 1000; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci venc_write_reg(VENC_F_CONTROL, 1<<8); 3308c2ecf20Sopenharmony_ci while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) { 3318c2ecf20Sopenharmony_ci if (--t == 0) { 3328c2ecf20Sopenharmony_ci DSSERR("Failed to reset venc\n"); 3338c2ecf20Sopenharmony_ci return; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_OMAP2_DSS_SLEEP_AFTER_VENC_RESET 3388c2ecf20Sopenharmony_ci /* the magical sleep that makes things work */ 3398c2ecf20Sopenharmony_ci /* XXX more info? What bug this circumvents? */ 3408c2ecf20Sopenharmony_ci msleep(20); 3418c2ecf20Sopenharmony_ci#endif 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic int venc_runtime_get(void) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci int r; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci DSSDBG("venc_runtime_get\n"); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci r = pm_runtime_get_sync(&venc.pdev->dev); 3518c2ecf20Sopenharmony_ci if (WARN_ON(r < 0)) { 3528c2ecf20Sopenharmony_ci pm_runtime_put_sync(&venc.pdev->dev); 3538c2ecf20Sopenharmony_ci return r; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci return 0; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic void venc_runtime_put(void) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci int r; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci DSSDBG("venc_runtime_put\n"); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci r = pm_runtime_put_sync(&venc.pdev->dev); 3658c2ecf20Sopenharmony_ci WARN_ON(r < 0 && r != -ENOSYS); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic const struct venc_config *venc_timings_to_config( 3698c2ecf20Sopenharmony_ci struct omap_video_timings *timings) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) 3728c2ecf20Sopenharmony_ci return &venc_config_pal_trm; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) 3758c2ecf20Sopenharmony_ci return &venc_config_ntsc_trm; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci BUG(); 3788c2ecf20Sopenharmony_ci return NULL; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic int venc_power_on(struct omap_dss_device *dssdev) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci struct omap_overlay_manager *mgr = venc.output.manager; 3848c2ecf20Sopenharmony_ci u32 l; 3858c2ecf20Sopenharmony_ci int r; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci r = venc_runtime_get(); 3888c2ecf20Sopenharmony_ci if (r) 3898c2ecf20Sopenharmony_ci goto err0; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci venc_reset(); 3928c2ecf20Sopenharmony_ci venc_write_config(venc_timings_to_config(&venc.timings)); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci dss_set_venc_output(venc.type); 3958c2ecf20Sopenharmony_ci dss_set_dac_pwrdn_bgz(1); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci l = 0; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) 4008c2ecf20Sopenharmony_ci l |= 1 << 1; 4018c2ecf20Sopenharmony_ci else /* S-Video */ 4028c2ecf20Sopenharmony_ci l |= (1 << 0) | (1 << 2); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci if (venc.invert_polarity == false) 4058c2ecf20Sopenharmony_ci l |= 1 << 3; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci venc_write_reg(VENC_OUTPUT_CONTROL, l); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci dss_mgr_set_timings(mgr, &venc.timings); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci r = regulator_enable(venc.vdda_dac_reg); 4128c2ecf20Sopenharmony_ci if (r) 4138c2ecf20Sopenharmony_ci goto err1; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci r = dss_mgr_enable(mgr); 4168c2ecf20Sopenharmony_ci if (r) 4178c2ecf20Sopenharmony_ci goto err2; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return 0; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cierr2: 4228c2ecf20Sopenharmony_ci regulator_disable(venc.vdda_dac_reg); 4238c2ecf20Sopenharmony_cierr1: 4248c2ecf20Sopenharmony_ci venc_write_reg(VENC_OUTPUT_CONTROL, 0); 4258c2ecf20Sopenharmony_ci dss_set_dac_pwrdn_bgz(0); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci venc_runtime_put(); 4288c2ecf20Sopenharmony_cierr0: 4298c2ecf20Sopenharmony_ci return r; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic void venc_power_off(struct omap_dss_device *dssdev) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci struct omap_overlay_manager *mgr = venc.output.manager; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci venc_write_reg(VENC_OUTPUT_CONTROL, 0); 4378c2ecf20Sopenharmony_ci dss_set_dac_pwrdn_bgz(0); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci dss_mgr_disable(mgr); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci regulator_disable(venc.vdda_dac_reg); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci venc_runtime_put(); 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic int venc_display_enable(struct omap_dss_device *dssdev) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci struct omap_dss_device *out = &venc.output; 4498c2ecf20Sopenharmony_ci int r; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci DSSDBG("venc_display_enable\n"); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci mutex_lock(&venc.venc_lock); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (out->manager == NULL) { 4568c2ecf20Sopenharmony_ci DSSERR("Failed to enable display: no output/manager\n"); 4578c2ecf20Sopenharmony_ci r = -ENODEV; 4588c2ecf20Sopenharmony_ci goto err0; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci r = venc_power_on(dssdev); 4628c2ecf20Sopenharmony_ci if (r) 4638c2ecf20Sopenharmony_ci goto err0; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci venc.wss_data = 0; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci return 0; 4708c2ecf20Sopenharmony_cierr0: 4718c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 4728c2ecf20Sopenharmony_ci return r; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic void venc_display_disable(struct omap_dss_device *dssdev) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci DSSDBG("venc_display_disable\n"); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci mutex_lock(&venc.venc_lock); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci venc_power_off(dssdev); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic void venc_set_timings(struct omap_dss_device *dssdev, 4878c2ecf20Sopenharmony_ci struct omap_video_timings *timings) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci DSSDBG("venc_set_timings\n"); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci mutex_lock(&venc.venc_lock); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci /* Reset WSS data when the TV standard changes. */ 4948c2ecf20Sopenharmony_ci if (memcmp(&venc.timings, timings, sizeof(*timings))) 4958c2ecf20Sopenharmony_ci venc.wss_data = 0; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci venc.timings = *timings; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci dispc_set_tv_pclk(13500000); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic int venc_check_timings(struct omap_dss_device *dssdev, 5058c2ecf20Sopenharmony_ci struct omap_video_timings *timings) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci DSSDBG("venc_check_timings\n"); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) 5108c2ecf20Sopenharmony_ci return 0; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) 5138c2ecf20Sopenharmony_ci return 0; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci return -EINVAL; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic void venc_get_timings(struct omap_dss_device *dssdev, 5198c2ecf20Sopenharmony_ci struct omap_video_timings *timings) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci mutex_lock(&venc.venc_lock); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci *timings = venc.timings; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic u32 venc_get_wss(struct omap_dss_device *dssdev) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci /* Invert due to VENC_L21_WC_CTL:INV=1 */ 5318c2ecf20Sopenharmony_ci return (venc.wss_data >> 8) ^ 0xfffff; 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci const struct venc_config *config; 5378c2ecf20Sopenharmony_ci int r; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci DSSDBG("venc_set_wss\n"); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci mutex_lock(&venc.venc_lock); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci config = venc_timings_to_config(&venc.timings); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci /* Invert due to VENC_L21_WC_CTL:INV=1 */ 5468c2ecf20Sopenharmony_ci venc.wss_data = (wss ^ 0xfffff) << 8; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci r = venc_runtime_get(); 5498c2ecf20Sopenharmony_ci if (r) 5508c2ecf20Sopenharmony_ci goto err; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | 5538c2ecf20Sopenharmony_ci venc.wss_data); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci venc_runtime_put(); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cierr: 5588c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci return r; 5618c2ecf20Sopenharmony_ci} 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_cistatic void venc_set_type(struct omap_dss_device *dssdev, 5648c2ecf20Sopenharmony_ci enum omap_dss_venc_type type) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci mutex_lock(&venc.venc_lock); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci venc.type = type; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cistatic void venc_invert_vid_out_polarity(struct omap_dss_device *dssdev, 5748c2ecf20Sopenharmony_ci bool invert_polarity) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci mutex_lock(&venc.venc_lock); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci venc.invert_polarity = invert_polarity; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci mutex_unlock(&venc.venc_lock); 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cistatic int venc_init_regulator(void) 5848c2ecf20Sopenharmony_ci{ 5858c2ecf20Sopenharmony_ci struct regulator *vdda_dac; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if (venc.vdda_dac_reg != NULL) 5888c2ecf20Sopenharmony_ci return 0; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci if (venc.pdev->dev.of_node) 5918c2ecf20Sopenharmony_ci vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda"); 5928c2ecf20Sopenharmony_ci else 5938c2ecf20Sopenharmony_ci vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac"); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci if (IS_ERR(vdda_dac)) { 5968c2ecf20Sopenharmony_ci if (PTR_ERR(vdda_dac) != -EPROBE_DEFER) 5978c2ecf20Sopenharmony_ci DSSERR("can't get VDDA_DAC regulator\n"); 5988c2ecf20Sopenharmony_ci return PTR_ERR(vdda_dac); 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci venc.vdda_dac_reg = vdda_dac; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci return 0; 6048c2ecf20Sopenharmony_ci} 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_cistatic void venc_dump_regs(struct seq_file *s) 6078c2ecf20Sopenharmony_ci{ 6088c2ecf20Sopenharmony_ci#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci if (venc_runtime_get()) 6118c2ecf20Sopenharmony_ci return; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci DUMPREG(VENC_F_CONTROL); 6148c2ecf20Sopenharmony_ci DUMPREG(VENC_VIDOUT_CTRL); 6158c2ecf20Sopenharmony_ci DUMPREG(VENC_SYNC_CTRL); 6168c2ecf20Sopenharmony_ci DUMPREG(VENC_LLEN); 6178c2ecf20Sopenharmony_ci DUMPREG(VENC_FLENS); 6188c2ecf20Sopenharmony_ci DUMPREG(VENC_HFLTR_CTRL); 6198c2ecf20Sopenharmony_ci DUMPREG(VENC_CC_CARR_WSS_CARR); 6208c2ecf20Sopenharmony_ci DUMPREG(VENC_C_PHASE); 6218c2ecf20Sopenharmony_ci DUMPREG(VENC_GAIN_U); 6228c2ecf20Sopenharmony_ci DUMPREG(VENC_GAIN_V); 6238c2ecf20Sopenharmony_ci DUMPREG(VENC_GAIN_Y); 6248c2ecf20Sopenharmony_ci DUMPREG(VENC_BLACK_LEVEL); 6258c2ecf20Sopenharmony_ci DUMPREG(VENC_BLANK_LEVEL); 6268c2ecf20Sopenharmony_ci DUMPREG(VENC_X_COLOR); 6278c2ecf20Sopenharmony_ci DUMPREG(VENC_M_CONTROL); 6288c2ecf20Sopenharmony_ci DUMPREG(VENC_BSTAMP_WSS_DATA); 6298c2ecf20Sopenharmony_ci DUMPREG(VENC_S_CARR); 6308c2ecf20Sopenharmony_ci DUMPREG(VENC_LINE21); 6318c2ecf20Sopenharmony_ci DUMPREG(VENC_LN_SEL); 6328c2ecf20Sopenharmony_ci DUMPREG(VENC_L21__WC_CTL); 6338c2ecf20Sopenharmony_ci DUMPREG(VENC_HTRIGGER_VTRIGGER); 6348c2ecf20Sopenharmony_ci DUMPREG(VENC_SAVID__EAVID); 6358c2ecf20Sopenharmony_ci DUMPREG(VENC_FLEN__FAL); 6368c2ecf20Sopenharmony_ci DUMPREG(VENC_LAL__PHASE_RESET); 6378c2ecf20Sopenharmony_ci DUMPREG(VENC_HS_INT_START_STOP_X); 6388c2ecf20Sopenharmony_ci DUMPREG(VENC_HS_EXT_START_STOP_X); 6398c2ecf20Sopenharmony_ci DUMPREG(VENC_VS_INT_START_X); 6408c2ecf20Sopenharmony_ci DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y); 6418c2ecf20Sopenharmony_ci DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X); 6428c2ecf20Sopenharmony_ci DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y); 6438c2ecf20Sopenharmony_ci DUMPREG(VENC_VS_EXT_STOP_Y); 6448c2ecf20Sopenharmony_ci DUMPREG(VENC_AVID_START_STOP_X); 6458c2ecf20Sopenharmony_ci DUMPREG(VENC_AVID_START_STOP_Y); 6468c2ecf20Sopenharmony_ci DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y); 6478c2ecf20Sopenharmony_ci DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X); 6488c2ecf20Sopenharmony_ci DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y); 6498c2ecf20Sopenharmony_ci DUMPREG(VENC_TVDETGP_INT_START_STOP_X); 6508c2ecf20Sopenharmony_ci DUMPREG(VENC_TVDETGP_INT_START_STOP_Y); 6518c2ecf20Sopenharmony_ci DUMPREG(VENC_GEN_CTRL); 6528c2ecf20Sopenharmony_ci DUMPREG(VENC_OUTPUT_CONTROL); 6538c2ecf20Sopenharmony_ci DUMPREG(VENC_OUTPUT_TEST); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci venc_runtime_put(); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci#undef DUMPREG 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cistatic int venc_get_clocks(struct platform_device *pdev) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci struct clk *clk; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { 6658c2ecf20Sopenharmony_ci clk = devm_clk_get(&pdev->dev, "tv_dac_clk"); 6668c2ecf20Sopenharmony_ci if (IS_ERR(clk)) { 6678c2ecf20Sopenharmony_ci DSSERR("can't get tv_dac_clk\n"); 6688c2ecf20Sopenharmony_ci return PTR_ERR(clk); 6698c2ecf20Sopenharmony_ci } 6708c2ecf20Sopenharmony_ci } else { 6718c2ecf20Sopenharmony_ci clk = NULL; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci venc.tv_dac_clk = clk; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci return 0; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic int venc_connect(struct omap_dss_device *dssdev, 6808c2ecf20Sopenharmony_ci struct omap_dss_device *dst) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci struct omap_overlay_manager *mgr; 6838c2ecf20Sopenharmony_ci int r; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci r = venc_init_regulator(); 6868c2ecf20Sopenharmony_ci if (r) 6878c2ecf20Sopenharmony_ci return r; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); 6908c2ecf20Sopenharmony_ci if (!mgr) 6918c2ecf20Sopenharmony_ci return -ENODEV; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci r = dss_mgr_connect(mgr, dssdev); 6948c2ecf20Sopenharmony_ci if (r) 6958c2ecf20Sopenharmony_ci return r; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci r = omapdss_output_set_device(dssdev, dst); 6988c2ecf20Sopenharmony_ci if (r) { 6998c2ecf20Sopenharmony_ci DSSERR("failed to connect output to new device: %s\n", 7008c2ecf20Sopenharmony_ci dst->name); 7018c2ecf20Sopenharmony_ci dss_mgr_disconnect(mgr, dssdev); 7028c2ecf20Sopenharmony_ci return r; 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci return 0; 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic void venc_disconnect(struct omap_dss_device *dssdev, 7098c2ecf20Sopenharmony_ci struct omap_dss_device *dst) 7108c2ecf20Sopenharmony_ci{ 7118c2ecf20Sopenharmony_ci WARN_ON(dst != dssdev->dst); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci if (dst != dssdev->dst) 7148c2ecf20Sopenharmony_ci return; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci omapdss_output_unset_device(dssdev); 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci if (dssdev->manager) 7198c2ecf20Sopenharmony_ci dss_mgr_disconnect(dssdev->manager, dssdev); 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_cistatic const struct omapdss_atv_ops venc_ops = { 7238c2ecf20Sopenharmony_ci .connect = venc_connect, 7248c2ecf20Sopenharmony_ci .disconnect = venc_disconnect, 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci .enable = venc_display_enable, 7278c2ecf20Sopenharmony_ci .disable = venc_display_disable, 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci .check_timings = venc_check_timings, 7308c2ecf20Sopenharmony_ci .set_timings = venc_set_timings, 7318c2ecf20Sopenharmony_ci .get_timings = venc_get_timings, 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci .set_type = venc_set_type, 7348c2ecf20Sopenharmony_ci .invert_vid_out_polarity = venc_invert_vid_out_polarity, 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci .set_wss = venc_set_wss, 7378c2ecf20Sopenharmony_ci .get_wss = venc_get_wss, 7388c2ecf20Sopenharmony_ci}; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_cistatic void venc_init_output(struct platform_device *pdev) 7418c2ecf20Sopenharmony_ci{ 7428c2ecf20Sopenharmony_ci struct omap_dss_device *out = &venc.output; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci out->dev = &pdev->dev; 7458c2ecf20Sopenharmony_ci out->id = OMAP_DSS_OUTPUT_VENC; 7468c2ecf20Sopenharmony_ci out->output_type = OMAP_DISPLAY_TYPE_VENC; 7478c2ecf20Sopenharmony_ci out->name = "venc.0"; 7488c2ecf20Sopenharmony_ci out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; 7498c2ecf20Sopenharmony_ci out->ops.atv = &venc_ops; 7508c2ecf20Sopenharmony_ci out->owner = THIS_MODULE; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci omapdss_register_output(out); 7538c2ecf20Sopenharmony_ci} 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistatic void venc_uninit_output(struct platform_device *pdev) 7568c2ecf20Sopenharmony_ci{ 7578c2ecf20Sopenharmony_ci struct omap_dss_device *out = &venc.output; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci omapdss_unregister_output(out); 7608c2ecf20Sopenharmony_ci} 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_cistatic int venc_probe_of(struct platform_device *pdev) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci struct device_node *node = pdev->dev.of_node; 7658c2ecf20Sopenharmony_ci struct device_node *ep; 7668c2ecf20Sopenharmony_ci u32 channels; 7678c2ecf20Sopenharmony_ci int r; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci ep = omapdss_of_get_first_endpoint(node); 7708c2ecf20Sopenharmony_ci if (!ep) 7718c2ecf20Sopenharmony_ci return 0; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity"); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci r = of_property_read_u32(ep, "ti,channels", &channels); 7768c2ecf20Sopenharmony_ci if (r) { 7778c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 7788c2ecf20Sopenharmony_ci "failed to read property 'ti,channels': %d\n", r); 7798c2ecf20Sopenharmony_ci goto err; 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci switch (channels) { 7838c2ecf20Sopenharmony_ci case 1: 7848c2ecf20Sopenharmony_ci venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE; 7858c2ecf20Sopenharmony_ci break; 7868c2ecf20Sopenharmony_ci case 2: 7878c2ecf20Sopenharmony_ci venc.type = OMAP_DSS_VENC_TYPE_SVIDEO; 7888c2ecf20Sopenharmony_ci break; 7898c2ecf20Sopenharmony_ci default: 7908c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "bad channel property '%d'\n", channels); 7918c2ecf20Sopenharmony_ci r = -EINVAL; 7928c2ecf20Sopenharmony_ci goto err; 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci of_node_put(ep); 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci return 0; 7988c2ecf20Sopenharmony_cierr: 7998c2ecf20Sopenharmony_ci of_node_put(ep); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci return 0; 8028c2ecf20Sopenharmony_ci} 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci/* VENC HW IP initialisation */ 8058c2ecf20Sopenharmony_cistatic int venc_bind(struct device *dev, struct device *master, void *data) 8068c2ecf20Sopenharmony_ci{ 8078c2ecf20Sopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 8088c2ecf20Sopenharmony_ci u8 rev_id; 8098c2ecf20Sopenharmony_ci struct resource *venc_mem; 8108c2ecf20Sopenharmony_ci int r; 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci venc.pdev = pdev; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci mutex_init(&venc.venc_lock); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci venc.wss_data = 0; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); 8198c2ecf20Sopenharmony_ci if (!venc_mem) { 8208c2ecf20Sopenharmony_ci DSSERR("can't get IORESOURCE_MEM VENC\n"); 8218c2ecf20Sopenharmony_ci return -EINVAL; 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci venc.base = devm_ioremap(&pdev->dev, venc_mem->start, 8258c2ecf20Sopenharmony_ci resource_size(venc_mem)); 8268c2ecf20Sopenharmony_ci if (!venc.base) { 8278c2ecf20Sopenharmony_ci DSSERR("can't ioremap VENC\n"); 8288c2ecf20Sopenharmony_ci return -ENOMEM; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci r = venc_get_clocks(pdev); 8328c2ecf20Sopenharmony_ci if (r) 8338c2ecf20Sopenharmony_ci return r; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci pm_runtime_enable(&pdev->dev); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci r = venc_runtime_get(); 8388c2ecf20Sopenharmony_ci if (r) 8398c2ecf20Sopenharmony_ci goto err_runtime_get; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); 8428c2ecf20Sopenharmony_ci dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci venc_runtime_put(); 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci if (pdev->dev.of_node) { 8478c2ecf20Sopenharmony_ci r = venc_probe_of(pdev); 8488c2ecf20Sopenharmony_ci if (r) { 8498c2ecf20Sopenharmony_ci DSSERR("Invalid DT data\n"); 8508c2ecf20Sopenharmony_ci goto err_probe_of; 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci } 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci dss_debugfs_create_file("venc", venc_dump_regs); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci venc_init_output(pdev); 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci return 0; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_cierr_probe_of: 8618c2ecf20Sopenharmony_cierr_runtime_get: 8628c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 8638c2ecf20Sopenharmony_ci return r; 8648c2ecf20Sopenharmony_ci} 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_cistatic void venc_unbind(struct device *dev, struct device *master, void *data) 8678c2ecf20Sopenharmony_ci{ 8688c2ecf20Sopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci venc_uninit_output(pdev); 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 8738c2ecf20Sopenharmony_ci} 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_cistatic const struct component_ops venc_component_ops = { 8768c2ecf20Sopenharmony_ci .bind = venc_bind, 8778c2ecf20Sopenharmony_ci .unbind = venc_unbind, 8788c2ecf20Sopenharmony_ci}; 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_cistatic int venc_probe(struct platform_device *pdev) 8818c2ecf20Sopenharmony_ci{ 8828c2ecf20Sopenharmony_ci return component_add(&pdev->dev, &venc_component_ops); 8838c2ecf20Sopenharmony_ci} 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_cistatic int venc_remove(struct platform_device *pdev) 8868c2ecf20Sopenharmony_ci{ 8878c2ecf20Sopenharmony_ci component_del(&pdev->dev, &venc_component_ops); 8888c2ecf20Sopenharmony_ci return 0; 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic int venc_runtime_suspend(struct device *dev) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci if (venc.tv_dac_clk) 8948c2ecf20Sopenharmony_ci clk_disable_unprepare(venc.tv_dac_clk); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci dispc_runtime_put(); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci return 0; 8998c2ecf20Sopenharmony_ci} 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_cistatic int venc_runtime_resume(struct device *dev) 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci int r; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci r = dispc_runtime_get(); 9068c2ecf20Sopenharmony_ci if (r < 0) 9078c2ecf20Sopenharmony_ci return r; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci if (venc.tv_dac_clk) 9108c2ecf20Sopenharmony_ci clk_prepare_enable(venc.tv_dac_clk); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci return 0; 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic const struct dev_pm_ops venc_pm_ops = { 9168c2ecf20Sopenharmony_ci .runtime_suspend = venc_runtime_suspend, 9178c2ecf20Sopenharmony_ci .runtime_resume = venc_runtime_resume, 9188c2ecf20Sopenharmony_ci}; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_cistatic const struct of_device_id venc_of_match[] = { 9218c2ecf20Sopenharmony_ci { .compatible = "ti,omap2-venc", }, 9228c2ecf20Sopenharmony_ci { .compatible = "ti,omap3-venc", }, 9238c2ecf20Sopenharmony_ci { .compatible = "ti,omap4-venc", }, 9248c2ecf20Sopenharmony_ci {}, 9258c2ecf20Sopenharmony_ci}; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_cistatic struct platform_driver omap_venchw_driver = { 9288c2ecf20Sopenharmony_ci .probe = venc_probe, 9298c2ecf20Sopenharmony_ci .remove = venc_remove, 9308c2ecf20Sopenharmony_ci .driver = { 9318c2ecf20Sopenharmony_ci .name = "omapdss_venc", 9328c2ecf20Sopenharmony_ci .pm = &venc_pm_ops, 9338c2ecf20Sopenharmony_ci .of_match_table = venc_of_match, 9348c2ecf20Sopenharmony_ci .suppress_bind_attrs = true, 9358c2ecf20Sopenharmony_ci }, 9368c2ecf20Sopenharmony_ci}; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ciint __init venc_init_platform_driver(void) 9398c2ecf20Sopenharmony_ci{ 9408c2ecf20Sopenharmony_ci return platform_driver_register(&omap_venchw_driver); 9418c2ecf20Sopenharmony_ci} 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_civoid venc_uninit_platform_driver(void) 9448c2ecf20Sopenharmony_ci{ 9458c2ecf20Sopenharmony_ci platform_driver_unregister(&omap_venchw_driver); 9468c2ecf20Sopenharmony_ci} 947