aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sti/sti_tvout.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/sti/sti_tvout.c')
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c104
1 files changed, 59 insertions, 45 deletions
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index b8afe490356a..cb924aa2b321 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -16,6 +16,8 @@
16#include <drm/drmP.h> 16#include <drm/drmP.h>
17#include <drm/drm_crtc_helper.h> 17#include <drm/drm_crtc_helper.h>
18 18
19#include "sti_drm_crtc.h"
20
19/* glue registers */ 21/* glue registers */
20#define TVO_CSC_MAIN_M0 0x000 22#define TVO_CSC_MAIN_M0 0x000
21#define TVO_CSC_MAIN_M1 0x004 23#define TVO_CSC_MAIN_M1 0x004
@@ -96,7 +98,7 @@
96 98
97#define TVO_SYNC_HD_DCS_SHIFT 8 99#define TVO_SYNC_HD_DCS_SHIFT 8
98 100
99#define ENCODER_MAIN_CRTC_MASK BIT(0) 101#define ENCODER_CRTC_MASK (BIT(0) | BIT(1))
100 102
101/* enum listing the supported output data format */ 103/* enum listing the supported output data format */
102enum sti_tvout_video_out_type { 104enum sti_tvout_video_out_type {
@@ -149,14 +151,15 @@ static void tvout_write(struct sti_tvout *tvout, u32 val, int offset)
149 * Set the clipping mode of a VIP 151 * Set the clipping mode of a VIP
150 * 152 *
151 * @tvout: tvout structure 153 * @tvout: tvout structure
154 * @reg: register to set
152 * @cr_r: 155 * @cr_r:
153 * @y_g: 156 * @y_g:
154 * @cb_b: 157 * @cb_b:
155 */ 158 */
156static void tvout_vip_set_color_order(struct sti_tvout *tvout, 159static void tvout_vip_set_color_order(struct sti_tvout *tvout, int reg,
157 u32 cr_r, u32 y_g, u32 cb_b) 160 u32 cr_r, u32 y_g, u32 cb_b)
158{ 161{
159 u32 val = tvout_read(tvout, TVO_VIP_HDMI); 162 u32 val = tvout_read(tvout, reg);
160 163
161 val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT); 164 val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT);
162 val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT); 165 val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT);
@@ -165,52 +168,58 @@ static void tvout_vip_set_color_order(struct sti_tvout *tvout,
165 val |= y_g << TVO_VIP_REORDER_G_SHIFT; 168 val |= y_g << TVO_VIP_REORDER_G_SHIFT;
166 val |= cb_b << TVO_VIP_REORDER_B_SHIFT; 169 val |= cb_b << TVO_VIP_REORDER_B_SHIFT;
167 170
168 tvout_write(tvout, val, TVO_VIP_HDMI); 171 tvout_write(tvout, val, reg);
169} 172}
170 173
171/** 174/**
172 * Set the clipping mode of a VIP 175 * Set the clipping mode of a VIP
173 * 176 *
174 * @tvout: tvout structure 177 * @tvout: tvout structure
178 * @reg: register to set
175 * @range: clipping range 179 * @range: clipping range
176 */ 180 */
177static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, u32 range) 181static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, int reg, u32 range)
178{ 182{
179 u32 val = tvout_read(tvout, TVO_VIP_HDMI); 183 u32 val = tvout_read(tvout, reg);
180 184
181 val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT); 185 val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT);
182 val |= range << TVO_VIP_CLIP_SHIFT; 186 val |= range << TVO_VIP_CLIP_SHIFT;
183 tvout_write(tvout, val, TVO_VIP_HDMI); 187 tvout_write(tvout, val, reg);
184} 188}
185 189
186/** 190/**
187 * Set the rounded value of a VIP 191 * Set the rounded value of a VIP
188 * 192 *
189 * @tvout: tvout structure 193 * @tvout: tvout structure
194 * @reg: register to set
190 * @rnd: rounded val per component 195 * @rnd: rounded val per component
191 */ 196 */
192static void tvout_vip_set_rnd(struct sti_tvout *tvout, u32 rnd) 197static void tvout_vip_set_rnd(struct sti_tvout *tvout, int reg, u32 rnd)
193{ 198{
194 u32 val = tvout_read(tvout, TVO_VIP_HDMI); 199 u32 val = tvout_read(tvout, reg);
195 200
196 val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT); 201 val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT);
197 val |= rnd << TVO_VIP_RND_SHIFT; 202 val |= rnd << TVO_VIP_RND_SHIFT;
198 tvout_write(tvout, val, TVO_VIP_HDMI); 203 tvout_write(tvout, val, reg);
199} 204}
200 205
201/** 206/**
202 * Select the VIP input 207 * Select the VIP input
203 * 208 *
204 * @tvout: tvout structure 209 * @tvout: tvout structure
210 * @reg: register to set
211 * @main_path: main or auxiliary path
212 * @sel_input_logic_inverted: need to invert the logic
205 * @sel_input: selected_input (main/aux + conv) 213 * @sel_input: selected_input (main/aux + conv)
206 */ 214 */
207static void tvout_vip_set_sel_input(struct sti_tvout *tvout, 215static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
216 int reg,
208 bool main_path, 217 bool main_path,
209 bool sel_input_logic_inverted, 218 bool sel_input_logic_inverted,
210 enum sti_tvout_video_out_type video_out) 219 enum sti_tvout_video_out_type video_out)
211{ 220{
212 u32 sel_input; 221 u32 sel_input;
213 u32 val = tvout_read(tvout, TVO_VIP_HDMI); 222 u32 val = tvout_read(tvout, reg);
214 223
215 if (main_path) 224 if (main_path)
216 sel_input = TVO_VIP_SEL_INPUT_MAIN; 225 sel_input = TVO_VIP_SEL_INPUT_MAIN;
@@ -232,22 +241,24 @@ static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
232 241
233 val &= ~TVO_VIP_SEL_INPUT_MASK; 242 val &= ~TVO_VIP_SEL_INPUT_MASK;
234 val |= sel_input; 243 val |= sel_input;
235 tvout_write(tvout, val, TVO_VIP_HDMI); 244 tvout_write(tvout, val, reg);
236} 245}
237 246
238/** 247/**
239 * Select the input video signed or unsigned 248 * Select the input video signed or unsigned
240 * 249 *
241 * @tvout: tvout structure 250 * @tvout: tvout structure
251 * @reg: register to set
242 * @in_vid_signed: used video input format 252 * @in_vid_signed: used video input format
243 */ 253 */
244static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, u32 in_vid_fmt) 254static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout,
255 int reg, u32 in_vid_fmt)
245{ 256{
246 u32 val = tvout_read(tvout, TVO_VIP_HDMI); 257 u32 val = tvout_read(tvout, reg);
247 258
248 val &= ~TVO_IN_FMT_SIGNED; 259 val &= ~TVO_IN_FMT_SIGNED;
249 val |= in_vid_fmt; 260 val |= in_vid_fmt;
250 tvout_write(tvout, val, TVO_MAIN_IN_VID_FORMAT); 261 tvout_write(tvout, val, reg);
251} 262}
252 263
253/** 264/**
@@ -261,6 +272,7 @@ static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path)
261{ 272{
262 struct device_node *node = tvout->dev->of_node; 273 struct device_node *node = tvout->dev->of_node;
263 bool sel_input_logic_inverted = false; 274 bool sel_input_logic_inverted = false;
275 u32 tvo_in_vid_format;
264 276
265 dev_dbg(tvout->dev, "%s\n", __func__); 277 dev_dbg(tvout->dev, "%s\n", __func__);
266 278
@@ -268,33 +280,36 @@ static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path)
268 DRM_DEBUG_DRIVER("main vip for hdmi\n"); 280 DRM_DEBUG_DRIVER("main vip for hdmi\n");
269 /* select the input sync for hdmi = VTG set 1 */ 281 /* select the input sync for hdmi = VTG set 1 */
270 tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL); 282 tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL);
283 tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
271 } else { 284 } else {
272 DRM_DEBUG_DRIVER("aux vip for hdmi\n"); 285 DRM_DEBUG_DRIVER("aux vip for hdmi\n");
273 /* select the input sync for hdmi = VTG set 1 */ 286 /* select the input sync for hdmi = VTG set 1 */
274 tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL); 287 tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL);
288 tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
275 } 289 }
276 290
277 /* set color channel order */ 291 /* set color channel order */
278 tvout_vip_set_color_order(tvout, 292 tvout_vip_set_color_order(tvout, TVO_VIP_HDMI,
279 TVO_VIP_REORDER_CR_R_SEL, 293 TVO_VIP_REORDER_CR_R_SEL,
280 TVO_VIP_REORDER_Y_G_SEL, 294 TVO_VIP_REORDER_Y_G_SEL,
281 TVO_VIP_REORDER_CB_B_SEL); 295 TVO_VIP_REORDER_CB_B_SEL);
282 296
283 /* set clipping mode (Limited range RGB/Y) */ 297 /* set clipping mode (Limited range RGB/Y) */
284 tvout_vip_set_clip_mode(tvout, TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y); 298 tvout_vip_set_clip_mode(tvout, TVO_VIP_HDMI,
299 TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y);
285 300
286 /* set round mode (rounded to 8-bit per component) */ 301 /* set round mode (rounded to 8-bit per component) */
287 tvout_vip_set_rnd(tvout, TVO_VIP_RND_8BIT_ROUNDED); 302 tvout_vip_set_rnd(tvout, TVO_VIP_HDMI, TVO_VIP_RND_8BIT_ROUNDED);
288 303
289 if (of_device_is_compatible(node, "st,stih407-tvout")) { 304 if (of_device_is_compatible(node, "st,stih407-tvout")) {
290 /* set input video format */ 305 /* set input video format */
291 tvout_vip_set_in_vid_fmt(tvout->regs + TVO_MAIN_IN_VID_FORMAT, 306 tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format,
292 TVO_IN_FMT_SIGNED); 307 TVO_IN_FMT_SIGNED);
293 sel_input_logic_inverted = true; 308 sel_input_logic_inverted = true;
294 } 309 }
295 310
296 /* input selection */ 311 /* input selection */
297 tvout_vip_set_sel_input(tvout, main_path, 312 tvout_vip_set_sel_input(tvout, TVO_VIP_HDMI, main_path,
298 sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB); 313 sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB);
299} 314}
300 315
@@ -309,48 +324,47 @@ static void tvout_hda_start(struct sti_tvout *tvout, bool main_path)
309{ 324{
310 struct device_node *node = tvout->dev->of_node; 325 struct device_node *node = tvout->dev->of_node;
311 bool sel_input_logic_inverted = false; 326 bool sel_input_logic_inverted = false;
327 u32 tvo_in_vid_format;
328 int val;
312 329
313 dev_dbg(tvout->dev, "%s\n", __func__); 330 dev_dbg(tvout->dev, "%s\n", __func__);
314 331
315 if (!main_path) { 332 if (main_path) {
316 DRM_ERROR("HD Analog on aux not implemented\n"); 333 val = TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT;
317 return; 334 val |= TVO_SYNC_MAIN_VTG_SET_3;
335 tvout_write(tvout, val, TVO_HD_SYNC_SEL);
336 tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
337 } else {
338 val = TVO_SYNC_AUX_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT;
339 val |= TVO_SYNC_AUX_VTG_SET_3;
340 tvout_write(tvout, val, TVO_HD_SYNC_SEL);
341 tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
318 } 342 }
319 343
320 DRM_DEBUG_DRIVER("main vip for HDF\n");
321
322 /* set color channel order */ 344 /* set color channel order */
323 tvout_vip_set_color_order(tvout->regs + TVO_VIP_HDF, 345 tvout_vip_set_color_order(tvout, TVO_VIP_HDF,
324 TVO_VIP_REORDER_CR_R_SEL, 346 TVO_VIP_REORDER_CR_R_SEL,
325 TVO_VIP_REORDER_Y_G_SEL, 347 TVO_VIP_REORDER_Y_G_SEL,
326 TVO_VIP_REORDER_CB_B_SEL); 348 TVO_VIP_REORDER_CB_B_SEL);
327 349
328 /* set clipping mode (Limited range RGB/Y) */ 350 /* set clipping mode (EAV/SAV clipping) */
329 tvout_vip_set_clip_mode(tvout->regs + TVO_VIP_HDF, 351 tvout_vip_set_clip_mode(tvout, TVO_VIP_HDF, TVO_VIP_CLIP_EAV_SAV);
330 TVO_VIP_CLIP_LIMITED_RANGE_CB_CR);
331 352
332 /* set round mode (rounded to 10-bit per component) */ 353 /* set round mode (rounded to 10-bit per component) */
333 tvout_vip_set_rnd(tvout->regs + TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED); 354 tvout_vip_set_rnd(tvout, TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED);
334 355
335 if (of_device_is_compatible(node, "st,stih407-tvout")) { 356 if (of_device_is_compatible(node, "st,stih407-tvout")) {
336 /* set input video format */ 357 /* set input video format */
337 tvout_vip_set_in_vid_fmt(tvout, TVO_IN_FMT_SIGNED); 358 tvout_vip_set_in_vid_fmt(tvout,
359 tvo_in_vid_format, TVO_IN_FMT_SIGNED);
338 sel_input_logic_inverted = true; 360 sel_input_logic_inverted = true;
339 } 361 }
340 362
341 /* Input selection */ 363 /* Input selection */
342 tvout_vip_set_sel_input(tvout->regs + TVO_VIP_HDF, 364 tvout_vip_set_sel_input(tvout, TVO_VIP_HDF, main_path,
343 main_path,
344 sel_input_logic_inverted, 365 sel_input_logic_inverted,
345 STI_TVOUT_VIDEO_OUT_YUV); 366 STI_TVOUT_VIDEO_OUT_YUV);
346 367
347 /* select the input sync for HD analog = VTG set 3
348 * and HD DCS = VTG set 2 */
349 tvout_write(tvout,
350 (TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT)
351 | TVO_SYNC_MAIN_VTG_SET_3,
352 TVO_HD_SYNC_SEL);
353
354 /* power up HD DAC */ 368 /* power up HD DAC */
355 tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF); 369 tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF);
356} 370}
@@ -392,7 +406,7 @@ static void sti_hda_encoder_commit(struct drm_encoder *encoder)
392{ 406{
393 struct sti_tvout *tvout = to_sti_tvout(encoder); 407 struct sti_tvout *tvout = to_sti_tvout(encoder);
394 408
395 tvout_hda_start(tvout, true); 409 tvout_hda_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
396} 410}
397 411
398static void sti_hda_encoder_disable(struct drm_encoder *encoder) 412static void sti_hda_encoder_disable(struct drm_encoder *encoder)
@@ -429,7 +443,7 @@ static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev,
429 443
430 drm_encoder = (struct drm_encoder *) encoder; 444 drm_encoder = (struct drm_encoder *) encoder;
431 445
432 drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK; 446 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
433 drm_encoder->possible_clones = 1 << 0; 447 drm_encoder->possible_clones = 1 << 0;
434 448
435 drm_encoder_init(dev, drm_encoder, 449 drm_encoder_init(dev, drm_encoder,
@@ -444,7 +458,7 @@ static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
444{ 458{
445 struct sti_tvout *tvout = to_sti_tvout(encoder); 459 struct sti_tvout *tvout = to_sti_tvout(encoder);
446 460
447 tvout_hdmi_start(tvout, true); 461 tvout_hdmi_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
448} 462}
449 463
450static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) 464static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
@@ -478,7 +492,7 @@ static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev,
478 492
479 drm_encoder = (struct drm_encoder *) encoder; 493 drm_encoder = (struct drm_encoder *) encoder;
480 494
481 drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK; 495 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
482 drm_encoder->possible_clones = 1 << 1; 496 drm_encoder->possible_clones = 1 << 1;
483 497
484 drm_encoder_init(dev, drm_encoder, 498 drm_encoder_init(dev, drm_encoder,