.. | .. |
---|
38 | 38 | .vrefresh = 60, 0, }, |
---|
39 | 39 | }; |
---|
40 | 40 | |
---|
| 41 | +struct env_config { |
---|
| 42 | + u32 offset; |
---|
| 43 | + u32 value; |
---|
| 44 | +}; |
---|
| 45 | + |
---|
| 46 | +static struct env_config ntsc_bt656_config[] = { |
---|
| 47 | + { BT656_DECODER_CROP, 0x00000000 }, |
---|
| 48 | + { BT656_DECODER_SIZE, 0x01e002d0 }, |
---|
| 49 | + { BT656_DECODER_HTOTAL_HS_END, 0x035a003e }, |
---|
| 50 | + { BT656_DECODER_VACT_ST_HACT_ST, 0x00160069 }, |
---|
| 51 | + { BT656_DECODER_VTOTAL_VS_END, 0x020d0003 }, |
---|
| 52 | + { BT656_DECODER_VS_ST_END_F1, 0x01060109 }, |
---|
| 53 | + { BT656_DECODER_DBG_REG, 0x024002d0 }, |
---|
| 54 | + { BT656_DECODER_CTRL, 0x00000009 }, |
---|
| 55 | +}; |
---|
| 56 | + |
---|
| 57 | +static struct env_config ntsc_tve_config[] = { |
---|
| 58 | + { TVE_MODE_CTRL, 0x000af906 }, |
---|
| 59 | + { TVE_HOR_TIMING1, 0x00c07a81 }, |
---|
| 60 | + { TVE_HOR_TIMING2, 0x169810fc }, |
---|
| 61 | + { TVE_HOR_TIMING3, 0x96b40000 }, |
---|
| 62 | + { TVE_SUB_CAR_FRQ, 0x21f07bd7 }, |
---|
| 63 | + { TVE_IMAGE_POSITION, 0x001500d6 }, |
---|
| 64 | + { TVE_ROUTING, 0x10088880 }, |
---|
| 65 | + { TVE_SYNC_ADJUST, 0x00000000 }, |
---|
| 66 | + { TVE_STATUS, 0x00000000 }, |
---|
| 67 | + { TVE_CTRL, 0x00000000 }, |
---|
| 68 | + { TVE_INTR_STATUS, 0x00000000 }, |
---|
| 69 | + { TVE_INTR_EN, 0x00000000 }, |
---|
| 70 | + { TVE_INTR_CLR, 0x00000000 }, |
---|
| 71 | + { TVE_COLOR_BUSRT_SAT, 0x0052543c }, |
---|
| 72 | + { TVE_CHROMA_BANDWIDTH, 0x00000002 }, |
---|
| 73 | + { TVE_BRIGHTNESS_CONTRAST, 0x00008300 }, |
---|
| 74 | + { TVE_CLAMP, 0x00000000 }, |
---|
| 75 | +}; |
---|
| 76 | + |
---|
| 77 | +static struct env_config pal_bt656_config[] = { |
---|
| 78 | + { BT656_DECODER_CROP, 0x00000000 }, |
---|
| 79 | + { BT656_DECODER_SIZE, 0x024002d0 }, |
---|
| 80 | + { BT656_DECODER_HTOTAL_HS_END, 0x0360003f }, |
---|
| 81 | + { BT656_DECODER_VACT_ST_HACT_ST, 0x0016006f }, |
---|
| 82 | + { BT656_DECODER_VTOTAL_VS_END, 0x02710003 }, |
---|
| 83 | + { BT656_DECODER_VS_ST_END_F1, 0x0138013b }, |
---|
| 84 | + { BT656_DECODER_DBG_REG, 0x024002d0 }, |
---|
| 85 | + { BT656_DECODER_CTRL, 0x00000009 }, |
---|
| 86 | +}; |
---|
| 87 | + |
---|
| 88 | +static struct env_config pal_tve_config[] = { |
---|
| 89 | + { TVE_MODE_CTRL, 0x010ab906 }, |
---|
| 90 | + { TVE_HOR_TIMING1, 0x00c28381 }, |
---|
| 91 | + { TVE_HOR_TIMING2, 0x267d111d }, |
---|
| 92 | + { TVE_HOR_TIMING3, 0x66c00880 }, |
---|
| 93 | + { TVE_SUB_CAR_FRQ, 0x2a098acb }, |
---|
| 94 | + { TVE_IMAGE_POSITION, 0x001500f6 }, |
---|
| 95 | + { TVE_ROUTING, 0x10008882 }, |
---|
| 96 | + { TVE_SYNC_ADJUST, 0x00000000 }, |
---|
| 97 | + { TVE_STATUS, 0x000000b0 }, |
---|
| 98 | + { TVE_CTRL, 0x00000000 }, |
---|
| 99 | + { TVE_INTR_STATUS, 0x00000000 }, |
---|
| 100 | + { TVE_INTR_EN, 0x00000000 }, |
---|
| 101 | + { TVE_INTR_CLR, 0x00000000 }, |
---|
| 102 | + { TVE_COLOR_BUSRT_SAT, 0x00356245 }, |
---|
| 103 | + { TVE_CHROMA_BANDWIDTH, 0x00000022 }, |
---|
| 104 | + { TVE_BRIGHTNESS_CONTRAST, 0x0000aa00 }, |
---|
| 105 | + { TVE_CLAMP, 0x00000000 }, |
---|
| 106 | +}; |
---|
| 107 | + |
---|
| 108 | +#define BT656_ENV_CONFIG_SIZE (sizeof(ntsc_bt656_config) / sizeof(struct env_config)) |
---|
| 109 | +#define TVE_ENV_CONFIG_SIZE (sizeof(ntsc_tve_config) / sizeof(struct env_config)) |
---|
| 110 | + |
---|
41 | 111 | #define tve_writel(offset, v) writel_relaxed(v, tve->regbase + (offset)) |
---|
42 | 112 | #define tve_readl(offset) readl_relaxed(tve->regbase + (offset)) |
---|
43 | 113 | |
---|
.. | .. |
---|
54 | 124 | int input_format; |
---|
55 | 125 | int soc_type; |
---|
56 | 126 | }; |
---|
| 127 | + |
---|
| 128 | +static void tve_write_block(struct rockchip_tve *tve, struct env_config *config, int len) |
---|
| 129 | +{ |
---|
| 130 | + int i; |
---|
| 131 | + |
---|
| 132 | + for (i = 0; i < len; i++) |
---|
| 133 | + tve_writel(config[i].offset, config[i].value); |
---|
| 134 | +} |
---|
57 | 135 | |
---|
58 | 136 | static int |
---|
59 | 137 | rockchip_tve_get_modes(struct drm_connector *connector) |
---|
.. | .. |
---|
107 | 185 | |
---|
108 | 186 | static void tve_set_mode(struct rockchip_tve *tve) |
---|
109 | 187 | { |
---|
| 188 | + struct env_config *bt656_cfg, *tve_cfg; |
---|
110 | 189 | int mode = tve->tv_format; |
---|
111 | 190 | |
---|
112 | | - dev_dbg(tve->dev, "tve set mode:%d\n", mode); |
---|
113 | | - if (tve->input_format == INPUT_FORMAT_RGB) |
---|
114 | | - tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) | |
---|
115 | | - v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) | |
---|
116 | | - v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0)); |
---|
117 | | - else |
---|
118 | | - tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) | |
---|
119 | | - v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) | |
---|
120 | | - v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(3)); |
---|
| 191 | + if (tve->soc_type == SOC_RK3528) { |
---|
| 192 | + tve_writel(TVE_LUMA_FILTER1, tve->lumafilter0); |
---|
| 193 | + tve_writel(TVE_LUMA_FILTER2, tve->lumafilter1); |
---|
| 194 | + tve_writel(TVE_LUMA_FILTER3, tve->lumafilter2); |
---|
| 195 | + tve_writel(TVE_LUMA_FILTER4, tve->lumafilter3); |
---|
| 196 | + tve_writel(TVE_LUMA_FILTER5, tve->lumafilter4); |
---|
| 197 | + tve_writel(TVE_LUMA_FILTER6, tve->lumafilter5); |
---|
| 198 | + tve_writel(TVE_LUMA_FILTER7, tve->lumafilter6); |
---|
| 199 | + tve_writel(TVE_LUMA_FILTER8, tve->lumafilter7); |
---|
| 200 | + } else { |
---|
| 201 | + dev_dbg(tve->dev, "tve set mode:%d\n", mode); |
---|
| 202 | + if (tve->input_format == INPUT_FORMAT_RGB) |
---|
| 203 | + tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) | |
---|
| 204 | + v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) | |
---|
| 205 | + v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0)); |
---|
| 206 | + else |
---|
| 207 | + tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) | |
---|
| 208 | + v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) | |
---|
| 209 | + v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(3)); |
---|
121 | 210 | |
---|
122 | | - tve_writel(TV_LUMA_FILTER0, tve->lumafilter0); |
---|
123 | | - tve_writel(TV_LUMA_FILTER1, tve->lumafilter1); |
---|
124 | | - tve_writel(TV_LUMA_FILTER2, tve->lumafilter2); |
---|
| 211 | + tve_writel(TV_LUMA_FILTER0, tve->lumafilter0); |
---|
| 212 | + tve_writel(TV_LUMA_FILTER1, tve->lumafilter1); |
---|
| 213 | + tve_writel(TV_LUMA_FILTER2, tve->lumafilter2); |
---|
| 214 | + } |
---|
125 | 215 | |
---|
126 | 216 | if (mode == TVOUT_CVBS_NTSC) { |
---|
127 | 217 | dev_dbg(tve->dev, "NTSC MODE\n"); |
---|
128 | | - tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) | |
---|
129 | | - v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) | |
---|
130 | | - v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode)); |
---|
131 | | - tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) | |
---|
132 | | - v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3)); |
---|
133 | | - tve_writel(TV_SATURATION, 0x0042543C); |
---|
134 | | - if (tve->test_mode) |
---|
135 | | - tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300); |
---|
136 | | - else |
---|
137 | | - tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900); |
---|
138 | 218 | |
---|
139 | | - tve_writel(TV_FREQ_SC, 0x21F07BD7); |
---|
140 | | - tve_writel(TV_SYNC_TIMING, 0x00C07a81); |
---|
141 | | - tve_writel(TV_ADJ_TIMING, 0x96B40000 | 0x70); |
---|
142 | | - tve_writel(TV_ACT_ST, 0x001500D6); |
---|
143 | | - tve_writel(TV_ACT_TIMING, 0x069800FC | (1 << 12) | (1 << 28)); |
---|
| 219 | + if (tve->soc_type == SOC_RK3528) { |
---|
| 220 | + bt656_cfg = ntsc_bt656_config; |
---|
| 221 | + tve_cfg = ntsc_tve_config; |
---|
144 | 222 | |
---|
| 223 | + tve_write_block(tve, bt656_cfg, BT656_ENV_CONFIG_SIZE); |
---|
| 224 | + tve_write_block(tve, tve_cfg, TVE_ENV_CONFIG_SIZE); |
---|
| 225 | + } else { |
---|
| 226 | + tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) | |
---|
| 227 | + v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) | |
---|
| 228 | + v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode)); |
---|
| 229 | + tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) | |
---|
| 230 | + v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3)); |
---|
| 231 | + tve_writel(TV_SATURATION, 0x0042543C); |
---|
| 232 | + if (tve->test_mode) |
---|
| 233 | + tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300); |
---|
| 234 | + else |
---|
| 235 | + tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900); |
---|
| 236 | + |
---|
| 237 | + tve_writel(TV_FREQ_SC, 0x21F07BD7); |
---|
| 238 | + tve_writel(TV_SYNC_TIMING, 0x00C07a81); |
---|
| 239 | + tve_writel(TV_ADJ_TIMING, 0x96B40000 | 0x70); |
---|
| 240 | + tve_writel(TV_ACT_ST, 0x001500D6); |
---|
| 241 | + tve_writel(TV_ACT_TIMING, 0x069800FC | (1 << 12) | (1 << 28)); |
---|
| 242 | + } |
---|
145 | 243 | } else if (mode == TVOUT_CVBS_PAL) { |
---|
146 | 244 | dev_dbg(tve->dev, "PAL MODE\n"); |
---|
147 | | - tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) | |
---|
148 | | - v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) | |
---|
149 | | - v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode)); |
---|
150 | | - tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_PAL) | |
---|
151 | | - v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3)); |
---|
152 | 245 | |
---|
153 | | - tve_writel(TV_SATURATION, tve->saturation); |
---|
154 | | - tve_writel(TV_BRIGHTNESS_CONTRAST, tve->brightcontrast); |
---|
| 246 | + if (tve->soc_type == SOC_RK3528) { |
---|
| 247 | + bt656_cfg = pal_bt656_config; |
---|
| 248 | + tve_cfg = pal_tve_config; |
---|
155 | 249 | |
---|
156 | | - tve_writel(TV_FREQ_SC, 0x2A098ACB); |
---|
157 | | - tve_writel(TV_SYNC_TIMING, 0x00C28381); |
---|
158 | | - tve_writel(TV_ADJ_TIMING, (0xc << 28) | 0x06c00800 | 0x80); |
---|
159 | | - tve_writel(TV_ACT_ST, 0x001500F6); |
---|
160 | | - tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28)); |
---|
| 250 | + tve_write_block(tve, bt656_cfg, BT656_ENV_CONFIG_SIZE); |
---|
| 251 | + tve_write_block(tve, tve_cfg, TVE_ENV_CONFIG_SIZE); |
---|
| 252 | + } else { |
---|
| 253 | + tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) | |
---|
| 254 | + v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) | |
---|
| 255 | + v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode)); |
---|
| 256 | + tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_PAL) | |
---|
| 257 | + v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3)); |
---|
161 | 258 | |
---|
162 | | - tve_writel(TV_ADJ_TIMING, tve->adjtiming); |
---|
163 | | - tve_writel(TV_ACT_TIMING, 0x0694011D | |
---|
164 | | - (1 << 12) | (2 << 28)); |
---|
| 259 | + tve_writel(TV_SATURATION, tve->saturation); |
---|
| 260 | + tve_writel(TV_BRIGHTNESS_CONTRAST, tve->brightcontrast); |
---|
| 261 | + |
---|
| 262 | + tve_writel(TV_FREQ_SC, 0x2A098ACB); |
---|
| 263 | + tve_writel(TV_SYNC_TIMING, 0x00C28381); |
---|
| 264 | + tve_writel(TV_ADJ_TIMING, (0xc << 28) | 0x06c00800 | 0x80); |
---|
| 265 | + tve_writel(TV_ACT_ST, 0x001500F6); |
---|
| 266 | + tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28)); |
---|
| 267 | + |
---|
| 268 | + tve_writel(TV_ADJ_TIMING, tve->adjtiming); |
---|
| 269 | + tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28)); |
---|
| 270 | + } |
---|
| 271 | + } |
---|
| 272 | + |
---|
| 273 | + if (tve->soc_type == SOC_RK3528) { |
---|
| 274 | + u32 upsample_mode = 0; |
---|
| 275 | + u32 mask = 0; |
---|
| 276 | + u32 val = 0; |
---|
| 277 | + bool upsample_en; |
---|
| 278 | + |
---|
| 279 | + upsample_en = tve->upsample_mode ? 1 : 0; |
---|
| 280 | + if (upsample_en) |
---|
| 281 | + upsample_mode = tve->upsample_mode - 1; |
---|
| 282 | + mask = m_TVE_DCLK_POL | m_TVE_DCLK_EN | m_DCLK_UPSAMPLE_2X4X | |
---|
| 283 | + m_DCLK_UPSAMPLE_EN | m_TVE_MODE | m_TVE_EN; |
---|
| 284 | + val = v_TVE_DCLK_POL(0) | v_TVE_DCLK_EN(1) | v_DCLK_UPSAMPLE_2X4X(upsample_mode) | |
---|
| 285 | + v_DCLK_UPSAMPLE_EN(upsample_en) | v_TVE_MODE(tve->tv_format) | v_TVE_EN(1); |
---|
| 286 | + |
---|
| 287 | + tve_dac_grf_writel(RK3528_VO_GRF_CVBS_CON, (mask << 16) | val); |
---|
165 | 288 | } |
---|
166 | 289 | } |
---|
167 | 290 | |
---|
.. | .. |
---|
178 | 301 | u32 mask = 0; |
---|
179 | 302 | u32 val = 0; |
---|
180 | 303 | u32 grfreg = 0; |
---|
| 304 | + u32 offset = 0; |
---|
181 | 305 | |
---|
182 | 306 | if (enable) { |
---|
183 | 307 | dev_dbg(tve->dev, "dac enable\n"); |
---|
184 | 308 | |
---|
185 | | - mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN; |
---|
186 | 309 | if (tve->soc_type == SOC_RK3036) { |
---|
| 310 | + mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN; |
---|
187 | 311 | val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel); |
---|
188 | 312 | grfreg = RK3036_GRF_SOC_CON3; |
---|
189 | 313 | } else if (tve->soc_type == SOC_RK312X) { |
---|
| 314 | + mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN; |
---|
190 | 315 | val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel); |
---|
191 | 316 | grfreg = RK312X_GRF_TVE_CON; |
---|
192 | 317 | } else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { |
---|
193 | 318 | val = v_CUR_REG(tve->dac1level) | v_DR_PWR_DOWN(0) | v_BG_PWR_DOWN(0); |
---|
| 319 | + offset = VDAC_VDAC1; |
---|
| 320 | + } else if (tve->soc_type == SOC_RK3528) { |
---|
| 321 | + /* |
---|
| 322 | + * Reset the vdac |
---|
| 323 | + */ |
---|
| 324 | + tve_dac_writel(VDAC_CLK_RST, v_ANALOG_RST(0) | v_DIGITAL_RST(0)); |
---|
| 325 | + msleep(20); |
---|
| 326 | + tve_dac_writel(VDAC_CLK_RST, v_ANALOG_RST(1) | v_DIGITAL_RST(1)); |
---|
| 327 | + |
---|
| 328 | + tve_dac_writel(VDAC_CURRENT_CTRL, v_OUT_CURRENT(tve->vdac_out_current)); |
---|
| 329 | + |
---|
| 330 | + val = v_REF_VOLTAGE(7) | v_DAC_PWN(1) | v_BIAS_PWN(1); |
---|
| 331 | + offset = VDAC_PWM_REF_CTRL; |
---|
194 | 332 | } |
---|
195 | 333 | } else { |
---|
196 | 334 | dev_dbg(tve->dev, "dac disable\n"); |
---|
197 | 335 | |
---|
198 | | - mask = m_VBG_EN | m_DAC_EN; |
---|
199 | | - if (tve->soc_type == SOC_RK312X) |
---|
| 336 | + if (tve->soc_type == SOC_RK312X) { |
---|
| 337 | + mask = m_VBG_EN | m_DAC_EN; |
---|
200 | 338 | grfreg = RK312X_GRF_TVE_CON; |
---|
201 | | - else if (tve->soc_type == SOC_RK3036) |
---|
| 339 | + } else if (tve->soc_type == SOC_RK3036) { |
---|
| 340 | + mask = m_VBG_EN | m_DAC_EN; |
---|
202 | 341 | grfreg = RK3036_GRF_SOC_CON3; |
---|
203 | | - else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) |
---|
| 342 | + } else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { |
---|
204 | 343 | val = v_CUR_REG(tve->dac1level) | m_DR_PWR_DOWN | m_BG_PWR_DOWN; |
---|
| 344 | + offset = VDAC_VDAC1; |
---|
| 345 | + } else if (tve->soc_type == SOC_RK3528) { |
---|
| 346 | + val = v_DAC_PWN(0) | v_BIAS_PWN(0); |
---|
| 347 | + offset = VDAC_PWM_REF_CTRL; |
---|
| 348 | + } |
---|
205 | 349 | } |
---|
206 | 350 | |
---|
207 | 351 | if (grfreg) |
---|
208 | 352 | tve_dac_grf_writel(grfreg, (mask << 16) | val); |
---|
209 | 353 | else if (tve->vdacbase) |
---|
210 | | - tve_dac_writel(VDAC_VDAC1, val); |
---|
| 354 | + tve_dac_writel(offset, val); |
---|
211 | 355 | } |
---|
212 | 356 | |
---|
213 | 357 | static int cvbs_set_disable(struct rockchip_tve *tve) |
---|
.. | .. |
---|
229 | 373 | return 0; |
---|
230 | 374 | } |
---|
231 | 375 | |
---|
| 376 | +/* |
---|
| 377 | + * RK3528 supports bt656 to cvbs, and the others support rgb to cvbs. |
---|
| 378 | + * |
---|
| 379 | + * ┌──────────┐ |
---|
| 380 | + * │ rgb data ├─────────────────────────────────────┐ |
---|
| 381 | + * └──────────┘ │ |
---|
| 382 | + * ▼ |
---|
| 383 | + * ┌────────────┐ ┌───────────────┐ ┌───────────────────┐ ┌──────┐ ┌────────┐ |
---|
| 384 | + * │ bt656 data ├───►│ bt656 decoder ├───►│ cvbs(tve) encoder ├───►│ vdac ├───►│ screen │ |
---|
| 385 | + * └────────────┘ └───────────────┘ └───────────────────┘ └──────┘ └────────┘ |
---|
| 386 | + * |
---|
| 387 | + */ |
---|
232 | 388 | static int cvbs_set_enable(struct rockchip_tve *tve) |
---|
233 | 389 | { |
---|
234 | 390 | int ret = 0; |
---|
.. | .. |
---|
242 | 398 | dev_err(tve->dev, "failed to get pm runtime: %d\n", ret); |
---|
243 | 399 | return ret; |
---|
244 | 400 | } |
---|
245 | | - dac_enable(tve, true); |
---|
246 | 401 | tve_set_mode(tve); |
---|
| 402 | + msleep(1000); |
---|
| 403 | + dac_enable(tve, true); |
---|
247 | 404 | tve->enable = 1; |
---|
248 | 405 | |
---|
249 | 406 | return 0; |
---|
.. | .. |
---|
264 | 421 | static void rockchip_tve_encoder_disable(struct drm_encoder *encoder) |
---|
265 | 422 | { |
---|
266 | 423 | struct rockchip_tve *tve = encoder_to_tve(encoder); |
---|
| 424 | + struct drm_crtc *crtc = encoder->crtc; |
---|
| 425 | + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); |
---|
267 | 426 | |
---|
268 | 427 | mutex_lock(&tve->suspend_lock); |
---|
269 | 428 | |
---|
.. | .. |
---|
271 | 430 | cvbs_set_disable(tve); |
---|
272 | 431 | |
---|
273 | 432 | mutex_unlock(&tve->suspend_lock); |
---|
| 433 | + |
---|
| 434 | + s->output_if &= ~VOP_OUTPUT_IF_TV; |
---|
274 | 435 | } |
---|
275 | 436 | |
---|
276 | 437 | static void rockchip_tve_encoder_mode_set(struct drm_encoder *encoder, |
---|
.. | .. |
---|
309 | 470 | struct drm_connector_state *conn_state) |
---|
310 | 471 | { |
---|
311 | 472 | struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); |
---|
| 473 | + struct rockchip_tve *tve = encoder_to_tve(encoder); |
---|
312 | 474 | struct drm_connector *connector = conn_state->connector; |
---|
313 | 475 | struct drm_display_info *info = &connector->display_info; |
---|
314 | 476 | |
---|
.. | .. |
---|
319 | 481 | else |
---|
320 | 482 | s->bus_format = MEDIA_BUS_FMT_YUV8_1X24; |
---|
321 | 483 | |
---|
| 484 | + /* |
---|
| 485 | + * For RK3528: |
---|
| 486 | + * VOP -> BT656 output -> BT656 decoder -> TVE encoder -> CVBS output |
---|
| 487 | + */ |
---|
| 488 | + if (tve->soc_type == SOC_RK3528) |
---|
| 489 | + s->output_if |= VOP_OUTPUT_IF_BT656; |
---|
| 490 | + else |
---|
| 491 | + s->output_if |= VOP_OUTPUT_IF_TV; |
---|
322 | 492 | s->color_space = V4L2_COLORSPACE_SMPTE170M; |
---|
323 | 493 | s->tv_state = &conn_state->tv; |
---|
324 | 494 | |
---|
.. | .. |
---|
354 | 524 | .atomic_check = rockchip_tve_encoder_atomic_check, |
---|
355 | 525 | }; |
---|
356 | 526 | |
---|
357 | | -static int tve_parse_dt(struct device_node *np, |
---|
358 | | - struct rockchip_tve *tve) |
---|
| 527 | +static int tve_read_otp_by_name(struct rockchip_tve *tve, char *name, u8 *val, u8 default_val) |
---|
| 528 | +{ |
---|
| 529 | + struct nvmem_cell *cell; |
---|
| 530 | + size_t len; |
---|
| 531 | + unsigned char *efuse_buf; |
---|
| 532 | + int ret = -EINVAL; |
---|
| 533 | + |
---|
| 534 | + *val = default_val; |
---|
| 535 | + cell = nvmem_cell_get(tve->dev, name); |
---|
| 536 | + if (!IS_ERR(cell)) { |
---|
| 537 | + efuse_buf = nvmem_cell_read(cell, &len); |
---|
| 538 | + nvmem_cell_put(cell); |
---|
| 539 | + if (!IS_ERR(efuse_buf)) { |
---|
| 540 | + *val = efuse_buf[0]; |
---|
| 541 | + kfree(efuse_buf); |
---|
| 542 | + return 0; |
---|
| 543 | + } |
---|
| 544 | + } |
---|
| 545 | + |
---|
| 546 | + dev_err(tve->dev, "failed to read %s from otp, use default\n", name); |
---|
| 547 | + |
---|
| 548 | + return ret; |
---|
| 549 | +} |
---|
| 550 | + |
---|
| 551 | +static int tve_parse_dt(struct device_node *np, struct rockchip_tve *tve) |
---|
| 552 | +{ |
---|
| 553 | + int ret, val; |
---|
| 554 | + u8 out_current, version; |
---|
| 555 | + |
---|
| 556 | + ret = of_property_read_u32(np, "rockchip,tvemode", &val); |
---|
| 557 | + if (ret < 0) { |
---|
| 558 | + tve->preferred_mode = 0; |
---|
| 559 | + } else if (val > 1) { |
---|
| 560 | + dev_err(tve->dev, "tve mode value invalid\n"); |
---|
| 561 | + return -EINVAL; |
---|
| 562 | + } |
---|
| 563 | + tve->preferred_mode = val; |
---|
| 564 | + |
---|
| 565 | + ret = of_property_read_u32(np, "rockchip,lumafilter0", &val); |
---|
| 566 | + if (val == 0 || ret < 0) |
---|
| 567 | + return -EINVAL; |
---|
| 568 | + tve->lumafilter0 = val; |
---|
| 569 | + |
---|
| 570 | + ret = of_property_read_u32(np, "rockchip,lumafilter1", &val); |
---|
| 571 | + if (val == 0 || ret < 0) |
---|
| 572 | + return -EINVAL; |
---|
| 573 | + tve->lumafilter1 = val; |
---|
| 574 | + |
---|
| 575 | + ret = of_property_read_u32(np, "rockchip,lumafilter2", &val); |
---|
| 576 | + if (val == 0 || ret < 0) |
---|
| 577 | + return -EINVAL; |
---|
| 578 | + tve->lumafilter2 = val; |
---|
| 579 | + |
---|
| 580 | + ret = of_property_read_u32(np, "rockchip,lumafilter3", &val); |
---|
| 581 | + if (val == 0 || ret < 0) |
---|
| 582 | + return -EINVAL; |
---|
| 583 | + tve->lumafilter3 = val; |
---|
| 584 | + |
---|
| 585 | + ret = of_property_read_u32(np, "rockchip,lumafilter4", &val); |
---|
| 586 | + if (val == 0 || ret < 0) |
---|
| 587 | + return -EINVAL; |
---|
| 588 | + tve->lumafilter4 = val; |
---|
| 589 | + |
---|
| 590 | + ret = of_property_read_u32(np, "rockchip,lumafilter5", &val); |
---|
| 591 | + if (val == 0 || ret < 0) |
---|
| 592 | + return -EINVAL; |
---|
| 593 | + tve->lumafilter5 = val; |
---|
| 594 | + |
---|
| 595 | + ret = of_property_read_u32(np, "rockchip,lumafilter6", &val); |
---|
| 596 | + if (val == 0 || ret < 0) |
---|
| 597 | + return -EINVAL; |
---|
| 598 | + tve->lumafilter6 = val; |
---|
| 599 | + |
---|
| 600 | + ret = of_property_read_u32(np, "rockchip,lumafilter7", &val); |
---|
| 601 | + if (val == 0 || ret < 0) |
---|
| 602 | + return -EINVAL; |
---|
| 603 | + tve->lumafilter7 = val; |
---|
| 604 | + |
---|
| 605 | + ret = of_property_read_u32(np, "rockchip,tve-upsample", &val); |
---|
| 606 | + if (val > DCLK_UPSAMPLEx4 || ret < 0) |
---|
| 607 | + return -EINVAL; |
---|
| 608 | + tve->upsample_mode = val; |
---|
| 609 | + |
---|
| 610 | + /* |
---|
| 611 | + * Read vdac output current from OTP if exists, and the default |
---|
| 612 | + * current val is 0xd2. |
---|
| 613 | + */ |
---|
| 614 | + ret = tve_read_otp_by_name(tve, "out-current", &out_current, 0xd2); |
---|
| 615 | + if (!ret) { |
---|
| 616 | + if (out_current) { |
---|
| 617 | + /* |
---|
| 618 | + * If test version is 0x0, the value of vdac out current |
---|
| 619 | + * needs to be reduced by one. |
---|
| 620 | + */ |
---|
| 621 | + ret = tve_read_otp_by_name(tve, "version", &version, 0x0); |
---|
| 622 | + if (!ret) { |
---|
| 623 | + if (version == 0x0) |
---|
| 624 | + out_current -= 1; |
---|
| 625 | + } |
---|
| 626 | + } else { |
---|
| 627 | + /* |
---|
| 628 | + * If the current value read from OTP is 0, set it to default. |
---|
| 629 | + */ |
---|
| 630 | + out_current = 0xd2; |
---|
| 631 | + } |
---|
| 632 | + } |
---|
| 633 | + tve->vdac_out_current = out_current; |
---|
| 634 | + |
---|
| 635 | + return 0; |
---|
| 636 | +} |
---|
| 637 | + |
---|
| 638 | +static int tve_parse_dt_legacy(struct device_node *np, struct rockchip_tve *tve) |
---|
359 | 639 | { |
---|
360 | 640 | int ret, val; |
---|
361 | 641 | u32 getdac = 0; |
---|
.. | .. |
---|
441 | 721 | return 0; |
---|
442 | 722 | } |
---|
443 | 723 | |
---|
| 724 | +static bool tve_check_lumafilter(struct rockchip_tve *tve) |
---|
| 725 | +{ |
---|
| 726 | + int lumafilter[8] = {INT_MAX}; |
---|
| 727 | + |
---|
| 728 | + /* |
---|
| 729 | + * The default lumafilter value is 0. If lumafilter value |
---|
| 730 | + * is equal to the dts value, uboot logo is enabled. |
---|
| 731 | + */ |
---|
| 732 | + if (tve->soc_type == SOC_RK3528) { |
---|
| 733 | + lumafilter[0] = tve_readl(TVE_LUMA_FILTER1); |
---|
| 734 | + lumafilter[1] = tve_readl(TVE_LUMA_FILTER2); |
---|
| 735 | + lumafilter[2] = tve_readl(TVE_LUMA_FILTER3); |
---|
| 736 | + lumafilter[3] = tve_readl(TVE_LUMA_FILTER4); |
---|
| 737 | + lumafilter[4] = tve_readl(TVE_LUMA_FILTER5); |
---|
| 738 | + lumafilter[5] = tve_readl(TVE_LUMA_FILTER6); |
---|
| 739 | + lumafilter[6] = tve_readl(TVE_LUMA_FILTER7); |
---|
| 740 | + lumafilter[7] = tve_readl(TVE_LUMA_FILTER8); |
---|
| 741 | + |
---|
| 742 | + if (lumafilter[0] == tve->lumafilter0 && |
---|
| 743 | + lumafilter[1] == tve->lumafilter1 && |
---|
| 744 | + lumafilter[2] == tve->lumafilter2 && |
---|
| 745 | + lumafilter[3] == tve->lumafilter3 && |
---|
| 746 | + lumafilter[4] == tve->lumafilter4 && |
---|
| 747 | + lumafilter[5] == tve->lumafilter5 && |
---|
| 748 | + lumafilter[6] == tve->lumafilter6 && |
---|
| 749 | + lumafilter[7] == tve->lumafilter7) { |
---|
| 750 | + return true; |
---|
| 751 | + } |
---|
| 752 | + } else { |
---|
| 753 | + lumafilter[0] = tve_readl(TV_LUMA_FILTER0); |
---|
| 754 | + lumafilter[1] = tve_readl(TV_LUMA_FILTER1); |
---|
| 755 | + lumafilter[2] = tve_readl(TV_LUMA_FILTER2); |
---|
| 756 | + |
---|
| 757 | + if (lumafilter[0] == tve->lumafilter0 && |
---|
| 758 | + lumafilter[1] == tve->lumafilter1 && |
---|
| 759 | + lumafilter[2] == tve->lumafilter2) { |
---|
| 760 | + return true; |
---|
| 761 | + } |
---|
| 762 | + } |
---|
| 763 | + |
---|
| 764 | + return false; |
---|
| 765 | +} |
---|
| 766 | + |
---|
444 | 767 | static void check_uboot_logo(struct rockchip_tve *tve) |
---|
445 | 768 | { |
---|
446 | | - int lumafilter0, lumafilter1, lumafilter2, vdac; |
---|
| 769 | + int vdac; |
---|
447 | 770 | |
---|
448 | 771 | if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { |
---|
449 | 772 | vdac = tve_dac_readl(VDAC_VDAC1); |
---|
.. | .. |
---|
454 | 777 | } |
---|
455 | 778 | } |
---|
456 | 779 | |
---|
457 | | - lumafilter0 = tve_readl(TV_LUMA_FILTER0); |
---|
458 | | - lumafilter1 = tve_readl(TV_LUMA_FILTER1); |
---|
459 | | - lumafilter2 = tve_readl(TV_LUMA_FILTER2); |
---|
460 | | - |
---|
461 | | - /* |
---|
462 | | - * The default lumafilter value is 0. If lumafilter value |
---|
463 | | - * is equal to the dts value, uboot logo is enabled. |
---|
464 | | - */ |
---|
465 | | - if (lumafilter0 == tve->lumafilter0 && |
---|
466 | | - lumafilter1 == tve->lumafilter1 && |
---|
467 | | - lumafilter2 == tve->lumafilter2) { |
---|
| 780 | + if (tve_check_lumafilter(tve)) { |
---|
468 | 781 | tve->connector.dpms = DRM_MODE_DPMS_ON; |
---|
469 | 782 | return; |
---|
470 | 783 | } |
---|
.. | .. |
---|
495 | 808 | .input_format = INPUT_FORMAT_YUV, |
---|
496 | 809 | }; |
---|
497 | 810 | |
---|
| 811 | +static const struct rockchip_tve_data rk3528_tve = { |
---|
| 812 | + .soc_type = SOC_RK3528, |
---|
| 813 | + .input_format = INPUT_FORMAT_YUV, |
---|
| 814 | +}; |
---|
| 815 | + |
---|
498 | 816 | static const struct of_device_id rockchip_tve_dt_ids[] = { |
---|
499 | 817 | { .compatible = "rockchip,rk3036-tve", .data = &rk3036_tve }, |
---|
500 | 818 | { .compatible = "rockchip,rk312x-tve", .data = &rk312x_tve }, |
---|
501 | 819 | { .compatible = "rockchip,rk322x-tve", .data = &rk322x_tve }, |
---|
502 | 820 | { .compatible = "rockchip,rk3328-tve", .data = &rk3328_tve }, |
---|
| 821 | + { .compatible = "rockchip,rk3528-tve", .data = &rk3528_tve }, |
---|
503 | 822 | {} |
---|
504 | 823 | }; |
---|
505 | 824 | |
---|
.. | .. |
---|
536 | 855 | tve->input_format = tve_data->input_format; |
---|
537 | 856 | } |
---|
538 | 857 | |
---|
539 | | - ret = tve_parse_dt(np, tve); |
---|
| 858 | + if (tve->soc_type == SOC_RK3528) |
---|
| 859 | + ret = tve_parse_dt(np, tve); |
---|
| 860 | + else |
---|
| 861 | + ret = tve_parse_dt_legacy(np, tve); |
---|
540 | 862 | if (ret) { |
---|
541 | 863 | dev_err(tve->dev, "TVE parse dts error!"); |
---|
542 | 864 | return -EINVAL; |
---|
543 | 865 | } |
---|
544 | 866 | |
---|
545 | 867 | tve->enable = 0; |
---|
546 | | - platform_set_drvdata(pdev, tve); |
---|
547 | 868 | tve->drm_dev = drm_dev; |
---|
548 | 869 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
549 | 870 | tve->reg_phy_base = res->start; |
---|
.. | .. |
---|
555 | 876 | return PTR_ERR(tve->regbase); |
---|
556 | 877 | } |
---|
557 | 878 | |
---|
558 | | - if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { |
---|
| 879 | + if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328 || |
---|
| 880 | + tve->soc_type == SOC_RK3528) { |
---|
559 | 881 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
---|
560 | 882 | tve->len = resource_size(res); |
---|
561 | 883 | tve->vdacbase = devm_ioremap(tve->dev, res->start, tve->len); |
---|
.. | .. |
---|
576 | 898 | if (ret) { |
---|
577 | 899 | dev_err(tve->dev, "Cannot enable tve aclk: %d\n", ret); |
---|
578 | 900 | return ret; |
---|
| 901 | + } |
---|
| 902 | + } else if (tve->soc_type == SOC_RK3528) { |
---|
| 903 | + tve->hclk = devm_clk_get(tve->dev, "hclk"); |
---|
| 904 | + if (IS_ERR(tve->hclk)) { |
---|
| 905 | + dev_err(tve->dev, "Unable to get tve hclk\n"); |
---|
| 906 | + return PTR_ERR(tve->hclk); |
---|
| 907 | + } |
---|
| 908 | + |
---|
| 909 | + ret = clk_prepare_enable(tve->hclk); |
---|
| 910 | + if (ret) { |
---|
| 911 | + dev_err(tve->dev, "Cannot enable tve hclk: %d\n", ret); |
---|
| 912 | + return ret; |
---|
| 913 | + } |
---|
| 914 | + |
---|
| 915 | + tve->pclk_vdac = devm_clk_get(tve->dev, "pclk_vdac"); |
---|
| 916 | + if (IS_ERR(tve->pclk_vdac)) { |
---|
| 917 | + dev_err(tve->dev, "Unable to get vdac pclk\n"); |
---|
| 918 | + return PTR_ERR(tve->pclk_vdac); |
---|
| 919 | + } |
---|
| 920 | + |
---|
| 921 | + ret = clk_prepare_enable(tve->pclk_vdac); |
---|
| 922 | + if (ret) { |
---|
| 923 | + dev_err(tve->dev, "Cannot enable vdac pclk: %d\n", ret); |
---|
| 924 | + return ret; |
---|
| 925 | + } |
---|
| 926 | + |
---|
| 927 | + tve->dclk = devm_clk_get(tve->dev, "dclk"); |
---|
| 928 | + if (IS_ERR(tve->dclk)) { |
---|
| 929 | + dev_err(tve->dev, "Unable to get tve dclk\n"); |
---|
| 930 | + return PTR_ERR(tve->dclk); |
---|
| 931 | + } |
---|
| 932 | + |
---|
| 933 | + ret = clk_prepare_enable(tve->dclk); |
---|
| 934 | + if (ret) { |
---|
| 935 | + dev_err(tve->dev, "Cannot enable tve dclk: %d\n", ret); |
---|
| 936 | + return ret; |
---|
| 937 | + } |
---|
| 938 | + |
---|
| 939 | + if (tve->upsample_mode == DCLK_UPSAMPLEx4) { |
---|
| 940 | + tve->dclk_4x = devm_clk_get(tve->dev, "dclk_4x"); |
---|
| 941 | + if (IS_ERR(tve->dclk_4x)) { |
---|
| 942 | + dev_err(tve->dev, "Unable to get tve dclk_4x\n"); |
---|
| 943 | + return PTR_ERR(tve->dclk_4x); |
---|
| 944 | + } |
---|
| 945 | + |
---|
| 946 | + ret = clk_prepare_enable(tve->dclk_4x); |
---|
| 947 | + if (ret) { |
---|
| 948 | + dev_err(tve->dev, "Cannot enable tve dclk_4x: %d\n", ret); |
---|
| 949 | + return ret; |
---|
| 950 | + } |
---|
579 | 951 | } |
---|
580 | 952 | } |
---|
581 | 953 | |
---|
.. | .. |
---|
621 | 993 | rockchip_drm_register_sub_dev(&tve->sub_dev); |
---|
622 | 994 | |
---|
623 | 995 | pm_runtime_enable(dev); |
---|
| 996 | + dev_set_drvdata(dev, tve); |
---|
624 | 997 | dev_dbg(tve->dev, "%s tv encoder probe ok\n", match->compatible); |
---|
625 | 998 | |
---|
626 | 999 | return 0; |
---|
.. | .. |
---|
648 | 1021 | drm_encoder_cleanup(&tve->encoder); |
---|
649 | 1022 | |
---|
650 | 1023 | pm_runtime_disable(dev); |
---|
| 1024 | + dev_set_drvdata(dev, NULL); |
---|
651 | 1025 | } |
---|
652 | 1026 | |
---|
653 | 1027 | static const struct component_ops rockchip_tve_component_ops = { |
---|
.. | .. |
---|
666 | 1040 | { |
---|
667 | 1041 | struct rockchip_tve *tve = dev_get_drvdata(&pdev->dev); |
---|
668 | 1042 | |
---|
| 1043 | + if (!tve) |
---|
| 1044 | + return; |
---|
| 1045 | + |
---|
669 | 1046 | mutex_lock(&tve->suspend_lock); |
---|
670 | 1047 | |
---|
671 | 1048 | dev_dbg(tve->dev, "tve shutdown\n"); |
---|