diff options
author | Tomasz Stanislawski <t.stanislaws@samsung.com> | 2012-02-03 12:02:17 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-20 08:01:56 -0400 |
commit | 3f468accf2ae2951dacebc04f186a08f495ce92a (patch) | |
tree | b1fa7d5316949ff60c1252ec060e538cb8997581 /drivers/media | |
parent | 2470ea3f7f14283efa2f427884efc6634e39f243 (diff) |
[media] v4l: s5p-tv: hdmi: parametrize DV timings
This patch fixes timings configuration in HDMI register. It adds
support for numerous new presets including interlaced ones.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/s5p-tv/hdmi_drv.c | 460 | ||||
-rw-r--r-- | drivers/media/video/s5p-tv/regs-hdmi.h | 1 |
2 files changed, 207 insertions, 254 deletions
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c index 4865d25a0e57..eefb903313c3 100644 --- a/drivers/media/video/s5p-tv/hdmi_drv.c +++ b/drivers/media/video/s5p-tv/hdmi_drv.c | |||
@@ -42,7 +42,23 @@ MODULE_DESCRIPTION("Samsung HDMI"); | |||
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | 43 | ||
44 | /* default preset configured on probe */ | 44 | /* default preset configured on probe */ |
45 | #define HDMI_DEFAULT_PRESET V4L2_DV_1080P60 | 45 | #define HDMI_DEFAULT_PRESET V4L2_DV_480P59_94 |
46 | |||
47 | struct hdmi_pulse { | ||
48 | u32 beg; | ||
49 | u32 end; | ||
50 | }; | ||
51 | |||
52 | struct hdmi_timings { | ||
53 | struct hdmi_pulse hact; | ||
54 | u32 hsyn_pol; /* 0 - high, 1 - low */ | ||
55 | struct hdmi_pulse hsyn; | ||
56 | u32 interlaced; | ||
57 | struct hdmi_pulse vact[2]; | ||
58 | u32 vsyn_pol; /* 0 - high, 1 - low */ | ||
59 | u32 vsyn_off; | ||
60 | struct hdmi_pulse vsyn[2]; | ||
61 | }; | ||
46 | 62 | ||
47 | struct hdmi_resources { | 63 | struct hdmi_resources { |
48 | struct clk *hdmi; | 64 | struct clk *hdmi; |
@@ -70,64 +86,13 @@ struct hdmi_device { | |||
70 | /** subdev of MHL interface */ | 86 | /** subdev of MHL interface */ |
71 | struct v4l2_subdev *mhl_sd; | 87 | struct v4l2_subdev *mhl_sd; |
72 | /** configuration of current graphic mode */ | 88 | /** configuration of current graphic mode */ |
73 | const struct hdmi_preset_conf *cur_conf; | 89 | const struct hdmi_timings *cur_conf; |
74 | /** current preset */ | 90 | /** current preset */ |
75 | u32 cur_preset; | 91 | u32 cur_preset; |
76 | /** other resources */ | 92 | /** other resources */ |
77 | struct hdmi_resources res; | 93 | struct hdmi_resources res; |
78 | }; | 94 | }; |
79 | 95 | ||
80 | struct hdmi_tg_regs { | ||
81 | u8 cmd; | ||
82 | u8 h_fsz_l; | ||
83 | u8 h_fsz_h; | ||
84 | u8 hact_st_l; | ||
85 | u8 hact_st_h; | ||
86 | u8 hact_sz_l; | ||
87 | u8 hact_sz_h; | ||
88 | u8 v_fsz_l; | ||
89 | u8 v_fsz_h; | ||
90 | u8 vsync_l; | ||
91 | u8 vsync_h; | ||
92 | u8 vsync2_l; | ||
93 | u8 vsync2_h; | ||
94 | u8 vact_st_l; | ||
95 | u8 vact_st_h; | ||
96 | u8 vact_sz_l; | ||
97 | u8 vact_sz_h; | ||
98 | u8 field_chg_l; | ||
99 | u8 field_chg_h; | ||
100 | u8 vact_st2_l; | ||
101 | u8 vact_st2_h; | ||
102 | u8 vsync_top_hdmi_l; | ||
103 | u8 vsync_top_hdmi_h; | ||
104 | u8 vsync_bot_hdmi_l; | ||
105 | u8 vsync_bot_hdmi_h; | ||
106 | u8 field_top_hdmi_l; | ||
107 | u8 field_top_hdmi_h; | ||
108 | u8 field_bot_hdmi_l; | ||
109 | u8 field_bot_hdmi_h; | ||
110 | }; | ||
111 | |||
112 | struct hdmi_core_regs { | ||
113 | u8 h_blank[2]; | ||
114 | u8 v_blank[3]; | ||
115 | u8 h_v_line[3]; | ||
116 | u8 vsync_pol[1]; | ||
117 | u8 int_pro_mode[1]; | ||
118 | u8 v_blank_f[3]; | ||
119 | u8 h_sync_gen[3]; | ||
120 | u8 v_sync_gen1[3]; | ||
121 | u8 v_sync_gen2[3]; | ||
122 | u8 v_sync_gen3[3]; | ||
123 | }; | ||
124 | |||
125 | struct hdmi_preset_conf { | ||
126 | struct hdmi_core_regs core; | ||
127 | struct hdmi_tg_regs tg; | ||
128 | struct v4l2_mbus_framefmt mbus_fmt; | ||
129 | }; | ||
130 | |||
131 | static struct platform_device_id hdmi_driver_types[] = { | 96 | static struct platform_device_id hdmi_driver_types[] = { |
132 | { | 97 | { |
133 | .name = "s5pv210-hdmi", | 98 | .name = "s5pv210-hdmi", |
@@ -165,6 +130,21 @@ void hdmi_writeb(struct hdmi_device *hdev, u32 reg_id, u8 value) | |||
165 | writeb(value, hdev->regs + reg_id); | 130 | writeb(value, hdev->regs + reg_id); |
166 | } | 131 | } |
167 | 132 | ||
133 | static inline | ||
134 | void hdmi_writebn(struct hdmi_device *hdev, u32 reg_id, int n, u32 value) | ||
135 | { | ||
136 | switch (n) { | ||
137 | default: | ||
138 | writeb(value >> 24, hdev->regs + reg_id + 12); | ||
139 | case 3: | ||
140 | writeb(value >> 16, hdev->regs + reg_id + 8); | ||
141 | case 2: | ||
142 | writeb(value >> 8, hdev->regs + reg_id + 4); | ||
143 | case 1: | ||
144 | writeb(value >> 0, hdev->regs + reg_id + 0); | ||
145 | } | ||
146 | } | ||
147 | |||
168 | static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id) | 148 | static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id) |
169 | { | 149 | { |
170 | return readl(hdev->regs + reg_id); | 150 | return readl(hdev->regs + reg_id); |
@@ -211,72 +191,63 @@ static void hdmi_reg_init(struct hdmi_device *hdev) | |||
211 | } | 191 | } |
212 | 192 | ||
213 | static void hdmi_timing_apply(struct hdmi_device *hdev, | 193 | static void hdmi_timing_apply(struct hdmi_device *hdev, |
214 | const struct hdmi_preset_conf *conf) | 194 | const struct hdmi_timings *t) |
215 | { | 195 | { |
216 | const struct hdmi_core_regs *core = &conf->core; | ||
217 | const struct hdmi_tg_regs *tg = &conf->tg; | ||
218 | |||
219 | /* setting core registers */ | 196 | /* setting core registers */ |
220 | hdmi_writeb(hdev, HDMI_H_BLANK_0, core->h_blank[0]); | 197 | hdmi_writebn(hdev, HDMI_H_BLANK_0, 2, t->hact.beg); |
221 | hdmi_writeb(hdev, HDMI_H_BLANK_1, core->h_blank[1]); | 198 | hdmi_writebn(hdev, HDMI_H_SYNC_GEN_0, 3, |
222 | hdmi_writeb(hdev, HDMI_V_BLANK_0, core->v_blank[0]); | 199 | (t->hsyn_pol << 20) | (t->hsyn.end << 10) | t->hsyn.beg); |
223 | hdmi_writeb(hdev, HDMI_V_BLANK_1, core->v_blank[1]); | 200 | hdmi_writeb(hdev, HDMI_VSYNC_POL, t->vsyn_pol); |
224 | hdmi_writeb(hdev, HDMI_V_BLANK_2, core->v_blank[2]); | 201 | hdmi_writebn(hdev, HDMI_V_BLANK_0, 3, |
225 | hdmi_writeb(hdev, HDMI_H_V_LINE_0, core->h_v_line[0]); | 202 | (t->vact[0].beg << 11) | t->vact[0].end); |
226 | hdmi_writeb(hdev, HDMI_H_V_LINE_1, core->h_v_line[1]); | 203 | hdmi_writebn(hdev, HDMI_V_SYNC_GEN_1_0, 3, |
227 | hdmi_writeb(hdev, HDMI_H_V_LINE_2, core->h_v_line[2]); | 204 | (t->vsyn[0].beg << 12) | t->vsyn[0].end); |
228 | hdmi_writeb(hdev, HDMI_VSYNC_POL, core->vsync_pol[0]); | 205 | if (t->interlaced) { |
229 | hdmi_writeb(hdev, HDMI_INT_PRO_MODE, core->int_pro_mode[0]); | 206 | u32 vsyn_trans = t->hsyn.beg + t->vsyn_off; |
230 | hdmi_writeb(hdev, HDMI_V_BLANK_F_0, core->v_blank_f[0]); | 207 | |
231 | hdmi_writeb(hdev, HDMI_V_BLANK_F_1, core->v_blank_f[1]); | 208 | hdmi_writeb(hdev, HDMI_INT_PRO_MODE, 1); |
232 | hdmi_writeb(hdev, HDMI_V_BLANK_F_2, core->v_blank_f[2]); | 209 | hdmi_writebn(hdev, HDMI_H_V_LINE_0, 3, |
233 | hdmi_writeb(hdev, HDMI_H_SYNC_GEN_0, core->h_sync_gen[0]); | 210 | (t->hact.end << 12) | t->vact[1].end); |
234 | hdmi_writeb(hdev, HDMI_H_SYNC_GEN_1, core->h_sync_gen[1]); | 211 | hdmi_writebn(hdev, HDMI_V_BLANK_F_0, 3, |
235 | hdmi_writeb(hdev, HDMI_H_SYNC_GEN_2, core->h_sync_gen[2]); | 212 | (t->vact[1].end << 11) | t->vact[1].beg); |
236 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_0, core->v_sync_gen1[0]); | 213 | hdmi_writebn(hdev, HDMI_V_SYNC_GEN_2_0, 3, |
237 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_1, core->v_sync_gen1[1]); | 214 | (t->vsyn[1].beg << 12) | t->vsyn[1].end); |
238 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_2, core->v_sync_gen1[2]); | 215 | hdmi_writebn(hdev, HDMI_V_SYNC_GEN_3_0, 3, |
239 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_0, core->v_sync_gen2[0]); | 216 | (vsyn_trans << 12) | vsyn_trans); |
240 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_1, core->v_sync_gen2[1]); | 217 | } else { |
241 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_2, core->v_sync_gen2[2]); | 218 | hdmi_writeb(hdev, HDMI_INT_PRO_MODE, 0); |
242 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_0, core->v_sync_gen3[0]); | 219 | hdmi_writebn(hdev, HDMI_H_V_LINE_0, 3, |
243 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_1, core->v_sync_gen3[1]); | 220 | (t->hact.end << 12) | t->vact[0].end); |
244 | hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_2, core->v_sync_gen3[2]); | 221 | } |
222 | |||
245 | /* Timing generator registers */ | 223 | /* Timing generator registers */ |
246 | hdmi_writeb(hdev, HDMI_TG_H_FSZ_L, tg->h_fsz_l); | 224 | hdmi_writebn(hdev, HDMI_TG_H_FSZ_L, 2, t->hact.end); |
247 | hdmi_writeb(hdev, HDMI_TG_H_FSZ_H, tg->h_fsz_h); | 225 | hdmi_writebn(hdev, HDMI_TG_HACT_ST_L, 2, t->hact.beg); |
248 | hdmi_writeb(hdev, HDMI_TG_HACT_ST_L, tg->hact_st_l); | 226 | hdmi_writebn(hdev, HDMI_TG_HACT_SZ_L, 2, t->hact.end - t->hact.beg); |
249 | hdmi_writeb(hdev, HDMI_TG_HACT_ST_H, tg->hact_st_h); | 227 | hdmi_writebn(hdev, HDMI_TG_VSYNC_L, 2, t->vsyn[0].beg); |
250 | hdmi_writeb(hdev, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); | 228 | hdmi_writebn(hdev, HDMI_TG_VACT_ST_L, 2, t->vact[0].beg); |
251 | hdmi_writeb(hdev, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); | 229 | hdmi_writebn(hdev, HDMI_TG_VACT_SZ_L, 2, |
252 | hdmi_writeb(hdev, HDMI_TG_V_FSZ_L, tg->v_fsz_l); | 230 | t->vact[0].end - t->vact[0].beg); |
253 | hdmi_writeb(hdev, HDMI_TG_V_FSZ_H, tg->v_fsz_h); | 231 | hdmi_writebn(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, 2, t->vsyn[0].beg); |
254 | hdmi_writeb(hdev, HDMI_TG_VSYNC_L, tg->vsync_l); | 232 | hdmi_writebn(hdev, HDMI_TG_FIELD_TOP_HDMI_L, 2, t->vsyn[0].beg); |
255 | hdmi_writeb(hdev, HDMI_TG_VSYNC_H, tg->vsync_h); | 233 | if (t->interlaced) { |
256 | hdmi_writeb(hdev, HDMI_TG_VSYNC2_L, tg->vsync2_l); | 234 | hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_FIELD_EN); |
257 | hdmi_writeb(hdev, HDMI_TG_VSYNC2_H, tg->vsync2_h); | 235 | hdmi_writebn(hdev, HDMI_TG_V_FSZ_L, 2, t->vact[1].end); |
258 | hdmi_writeb(hdev, HDMI_TG_VACT_ST_L, tg->vact_st_l); | 236 | hdmi_writebn(hdev, HDMI_TG_VSYNC2_L, 2, t->vsyn[1].beg); |
259 | hdmi_writeb(hdev, HDMI_TG_VACT_ST_H, tg->vact_st_h); | 237 | hdmi_writebn(hdev, HDMI_TG_FIELD_CHG_L, 2, t->vact[0].end); |
260 | hdmi_writeb(hdev, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); | 238 | hdmi_writebn(hdev, HDMI_TG_VACT_ST2_L, 2, t->vact[1].beg); |
261 | hdmi_writeb(hdev, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); | 239 | hdmi_writebn(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, 2, t->vsyn[1].beg); |
262 | hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); | 240 | hdmi_writebn(hdev, HDMI_TG_FIELD_BOT_HDMI_L, 2, t->vsyn[1].beg); |
263 | hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); | 241 | } else { |
264 | hdmi_writeb(hdev, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); | 242 | hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_FIELD_EN); |
265 | hdmi_writeb(hdev, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); | 243 | hdmi_writebn(hdev, HDMI_TG_V_FSZ_L, 2, t->vact[0].end); |
266 | hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); | 244 | } |
267 | hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); | ||
268 | hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); | ||
269 | hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); | ||
270 | hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); | ||
271 | hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); | ||
272 | hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); | ||
273 | hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); | ||
274 | } | 245 | } |
275 | 246 | ||
276 | static int hdmi_conf_apply(struct hdmi_device *hdmi_dev) | 247 | static int hdmi_conf_apply(struct hdmi_device *hdmi_dev) |
277 | { | 248 | { |
278 | struct device *dev = hdmi_dev->dev; | 249 | struct device *dev = hdmi_dev->dev; |
279 | const struct hdmi_preset_conf *conf = hdmi_dev->cur_conf; | 250 | const struct hdmi_timings *conf = hdmi_dev->cur_conf; |
280 | struct v4l2_dv_preset preset; | 251 | struct v4l2_dv_preset preset; |
281 | int ret; | 252 | int ret; |
282 | 253 | ||
@@ -398,156 +369,126 @@ static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix) | |||
398 | #undef DUMPREG | 369 | #undef DUMPREG |
399 | } | 370 | } |
400 | 371 | ||
401 | static const struct hdmi_preset_conf hdmi_conf_480p = { | 372 | static const struct hdmi_timings hdmi_timings_480p = { |
402 | .core = { | 373 | .hact = { .beg = 138, .end = 858 }, |
403 | .h_blank = {0x8a, 0x00}, | 374 | .hsyn_pol = 1, |
404 | .v_blank = {0x0d, 0x6a, 0x01}, | 375 | .hsyn = { .beg = 16, .end = 16 + 62 }, |
405 | .h_v_line = {0x0d, 0xa2, 0x35}, | 376 | .interlaced = 0, |
406 | .vsync_pol = {0x01}, | 377 | .vact[0] = { .beg = 42 + 3, .end = 522 + 3 }, |
407 | .int_pro_mode = {0x00}, | 378 | .vsyn_pol = 1, |
408 | .v_blank_f = {0x00, 0x00, 0x00}, | 379 | .vsyn[0] = { .beg = 6 + 3, .end = 12 + 3}, |
409 | .h_sync_gen = {0x0e, 0x30, 0x11}, | 380 | }; |
410 | .v_sync_gen1 = {0x0f, 0x90, 0x00}, | 381 | |
411 | /* other don't care */ | 382 | static const struct hdmi_timings hdmi_timings_576p50 = { |
412 | }, | 383 | .hact = { .beg = 144, .end = 864 }, |
413 | .tg = { | 384 | .hsyn_pol = 1, |
414 | 0x00, /* cmd */ | 385 | .hsyn = { .beg = 12, .end = 12 + 64 }, |
415 | 0x5a, 0x03, /* h_fsz */ | 386 | .interlaced = 0, |
416 | 0x8a, 0x00, 0xd0, 0x02, /* hact */ | 387 | .vact[0] = { .beg = 44 + 5, .end = 620 + 5 }, |
417 | 0x0d, 0x02, /* v_fsz */ | 388 | .vsyn_pol = 1, |
418 | 0x01, 0x00, 0x33, 0x02, /* vsync */ | 389 | .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5}, |
419 | 0x2d, 0x00, 0xe0, 0x01, /* vact */ | 390 | }; |
420 | 0x33, 0x02, /* field_chg */ | 391 | |
421 | 0x49, 0x02, /* vact_st2 */ | 392 | static const struct hdmi_timings hdmi_timings_720p60 = { |
422 | 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ | 393 | .hact = { .beg = 370, .end = 1650 }, |
423 | 0x01, 0x00, 0x33, 0x02, /* field top/bot */ | 394 | .hsyn_pol = 0, |
424 | }, | 395 | .hsyn = { .beg = 110, .end = 110 + 40 }, |
425 | .mbus_fmt = { | 396 | .interlaced = 0, |
426 | .width = 720, | 397 | .vact[0] = { .beg = 25 + 5, .end = 745 + 5 }, |
427 | .height = 480, | 398 | .vsyn_pol = 0, |
428 | .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */ | 399 | .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5}, |
429 | .field = V4L2_FIELD_NONE, | 400 | }; |
430 | .colorspace = V4L2_COLORSPACE_SRGB, | 401 | |
431 | }, | 402 | static const struct hdmi_timings hdmi_timings_720p50 = { |
403 | .hact = { .beg = 700, .end = 1980 }, | ||
404 | .hsyn_pol = 0, | ||
405 | .hsyn = { .beg = 440, .end = 440 + 40 }, | ||
406 | .interlaced = 0, | ||
407 | .vact[0] = { .beg = 25 + 5, .end = 745 + 5 }, | ||
408 | .vsyn_pol = 0, | ||
409 | .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5}, | ||
410 | }; | ||
411 | |||
412 | static const struct hdmi_timings hdmi_timings_1080p24 = { | ||
413 | .hact = { .beg = 830, .end = 2750 }, | ||
414 | .hsyn_pol = 0, | ||
415 | .hsyn = { .beg = 638, .end = 638 + 44 }, | ||
416 | .interlaced = 0, | ||
417 | .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 }, | ||
418 | .vsyn_pol = 0, | ||
419 | .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4}, | ||
420 | }; | ||
421 | |||
422 | static const struct hdmi_timings hdmi_timings_1080p60 = { | ||
423 | .hact = { .beg = 280, .end = 2200 }, | ||
424 | .hsyn_pol = 0, | ||
425 | .hsyn = { .beg = 88, .end = 88 + 44 }, | ||
426 | .interlaced = 0, | ||
427 | .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 }, | ||
428 | .vsyn_pol = 0, | ||
429 | .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4}, | ||
432 | }; | 430 | }; |
433 | 431 | ||
434 | static const struct hdmi_preset_conf hdmi_conf_720p60 = { | 432 | static const struct hdmi_timings hdmi_timings_1080i60 = { |
435 | .core = { | 433 | .hact = { .beg = 280, .end = 2200 }, |
436 | .h_blank = {0x72, 0x01}, | 434 | .hsyn_pol = 0, |
437 | .v_blank = {0xee, 0xf2, 0x00}, | 435 | .hsyn = { .beg = 88, .end = 88 + 44 }, |
438 | .h_v_line = {0xee, 0x22, 0x67}, | 436 | .interlaced = 1, |
439 | .vsync_pol = {0x00}, | 437 | .vact[0] = { .beg = 20 + 2, .end = 560 + 2 }, |
440 | .int_pro_mode = {0x00}, | 438 | .vact[1] = { .beg = 583 + 2, .end = 1123 + 2 }, |
441 | .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ | 439 | .vsyn_pol = 0, |
442 | .h_sync_gen = {0x6c, 0x50, 0x02}, | 440 | .vsyn_off = 1100, |
443 | .v_sync_gen1 = {0x0a, 0x50, 0x00}, | 441 | .vsyn[0] = { .beg = 0 + 2, .end = 5 + 2}, |
444 | /* other don't care */ | 442 | .vsyn[1] = { .beg = 562 + 2, .end = 567 + 2}, |
445 | }, | ||
446 | .tg = { | ||
447 | 0x00, /* cmd */ | ||
448 | 0x72, 0x06, /* h_fsz */ | ||
449 | 0x72, 0x01, 0x00, 0x05, /* hact */ | ||
450 | 0xee, 0x02, /* v_fsz */ | ||
451 | 0x01, 0x00, 0x33, 0x02, /* vsync */ | ||
452 | 0x1e, 0x00, 0xd0, 0x02, /* vact */ | ||
453 | 0x33, 0x02, /* field_chg */ | ||
454 | 0x49, 0x02, /* vact_st2 */ | ||
455 | 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ | ||
456 | 0x01, 0x00, 0x33, 0x02, /* field top/bot */ | ||
457 | }, | ||
458 | .mbus_fmt = { | ||
459 | .width = 1280, | ||
460 | .height = 720, | ||
461 | .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */ | ||
462 | .field = V4L2_FIELD_NONE, | ||
463 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
464 | }, | ||
465 | }; | 443 | }; |
466 | 444 | ||
467 | static const struct hdmi_preset_conf hdmi_conf_1080p50 = { | 445 | static const struct hdmi_timings hdmi_timings_1080i50 = { |
468 | .core = { | 446 | .hact = { .beg = 720, .end = 2640 }, |
469 | .h_blank = {0xd0, 0x02}, | 447 | .hsyn_pol = 0, |
470 | .v_blank = {0x65, 0x6c, 0x01}, | 448 | .hsyn = { .beg = 528, .end = 528 + 44 }, |
471 | .h_v_line = {0x65, 0x04, 0xa5}, | 449 | .interlaced = 1, |
472 | .vsync_pol = {0x00}, | 450 | .vact[0] = { .beg = 20 + 2, .end = 560 + 2 }, |
473 | .int_pro_mode = {0x00}, | 451 | .vact[1] = { .beg = 583 + 2, .end = 1123 + 2 }, |
474 | .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ | 452 | .vsyn_pol = 0, |
475 | .h_sync_gen = {0x0e, 0xea, 0x08}, | 453 | .vsyn_off = 1320, |
476 | .v_sync_gen1 = {0x09, 0x40, 0x00}, | 454 | .vsyn[0] = { .beg = 0 + 2, .end = 5 + 2}, |
477 | /* other don't care */ | 455 | .vsyn[1] = { .beg = 562 + 2, .end = 567 + 2}, |
478 | }, | ||
479 | .tg = { | ||
480 | 0x00, /* cmd */ | ||
481 | 0x98, 0x08, /* h_fsz */ | ||
482 | 0x18, 0x01, 0x80, 0x07, /* hact */ | ||
483 | 0x65, 0x04, /* v_fsz */ | ||
484 | 0x01, 0x00, 0x33, 0x02, /* vsync */ | ||
485 | 0x2d, 0x00, 0x38, 0x04, /* vact */ | ||
486 | 0x33, 0x02, /* field_chg */ | ||
487 | 0x49, 0x02, /* vact_st2 */ | ||
488 | 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ | ||
489 | 0x01, 0x00, 0x33, 0x02, /* field top/bot */ | ||
490 | }, | ||
491 | .mbus_fmt = { | ||
492 | .width = 1920, | ||
493 | .height = 1080, | ||
494 | .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */ | ||
495 | .field = V4L2_FIELD_NONE, | ||
496 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
497 | }, | ||
498 | }; | 456 | }; |
499 | 457 | ||
500 | static const struct hdmi_preset_conf hdmi_conf_1080p60 = { | 458 | static const struct hdmi_timings hdmi_timings_1080p50 = { |
501 | .core = { | 459 | .hact = { .beg = 720, .end = 2640 }, |
502 | .h_blank = {0x18, 0x01}, | 460 | .hsyn_pol = 0, |
503 | .v_blank = {0x65, 0x6c, 0x01}, | 461 | .hsyn = { .beg = 528, .end = 528 + 44 }, |
504 | .h_v_line = {0x65, 0x84, 0x89}, | 462 | .interlaced = 0, |
505 | .vsync_pol = {0x00}, | 463 | .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 }, |
506 | .int_pro_mode = {0x00}, | 464 | .vsyn_pol = 0, |
507 | .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ | 465 | .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4}, |
508 | .h_sync_gen = {0x56, 0x08, 0x02}, | ||
509 | .v_sync_gen1 = {0x09, 0x40, 0x00}, | ||
510 | /* other don't care */ | ||
511 | }, | ||
512 | .tg = { | ||
513 | 0x00, /* cmd */ | ||
514 | 0x98, 0x08, /* h_fsz */ | ||
515 | 0x18, 0x01, 0x80, 0x07, /* hact */ | ||
516 | 0x65, 0x04, /* v_fsz */ | ||
517 | 0x01, 0x00, 0x33, 0x02, /* vsync */ | ||
518 | 0x2d, 0x00, 0x38, 0x04, /* vact */ | ||
519 | 0x33, 0x02, /* field_chg */ | ||
520 | 0x48, 0x02, /* vact_st2 */ | ||
521 | 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ | ||
522 | 0x01, 0x00, 0x33, 0x02, /* field top/bot */ | ||
523 | }, | ||
524 | .mbus_fmt = { | ||
525 | .width = 1920, | ||
526 | .height = 1080, | ||
527 | .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */ | ||
528 | .field = V4L2_FIELD_NONE, | ||
529 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
530 | }, | ||
531 | }; | 466 | }; |
532 | 467 | ||
533 | static const struct { | 468 | static const struct { |
534 | u32 preset; | 469 | u32 preset; |
535 | const struct hdmi_preset_conf *conf; | 470 | const struct hdmi_timings *timings; |
536 | } hdmi_conf[] = { | 471 | } hdmi_timings[] = { |
537 | { V4L2_DV_480P59_94, &hdmi_conf_480p }, | 472 | { V4L2_DV_480P59_94, &hdmi_timings_480p }, |
538 | { V4L2_DV_720P59_94, &hdmi_conf_720p60 }, | 473 | { V4L2_DV_576P50, &hdmi_timings_576p50 }, |
539 | { V4L2_DV_1080P50, &hdmi_conf_1080p50 }, | 474 | { V4L2_DV_720P50, &hdmi_timings_720p50 }, |
540 | { V4L2_DV_1080P30, &hdmi_conf_1080p60 }, | 475 | { V4L2_DV_720P59_94, &hdmi_timings_720p60 }, |
541 | { V4L2_DV_1080P60, &hdmi_conf_1080p60 }, | 476 | { V4L2_DV_720P60, &hdmi_timings_720p60 }, |
477 | { V4L2_DV_1080P24, &hdmi_timings_1080p24 }, | ||
478 | { V4L2_DV_1080P30, &hdmi_timings_1080p60 }, | ||
479 | { V4L2_DV_1080P50, &hdmi_timings_1080p50 }, | ||
480 | { V4L2_DV_1080I50, &hdmi_timings_1080i50 }, | ||
481 | { V4L2_DV_1080I60, &hdmi_timings_1080i60 }, | ||
482 | { V4L2_DV_1080P60, &hdmi_timings_1080p60 }, | ||
542 | }; | 483 | }; |
543 | 484 | ||
544 | static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset) | 485 | static const struct hdmi_timings *hdmi_preset2timings(u32 preset) |
545 | { | 486 | { |
546 | int i; | 487 | int i; |
547 | 488 | ||
548 | for (i = 0; i < ARRAY_SIZE(hdmi_conf); ++i) | 489 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); ++i) |
549 | if (hdmi_conf[i].preset == preset) | 490 | if (hdmi_timings[i].preset == preset) |
550 | return hdmi_conf[i].conf; | 491 | return hdmi_timings[i].timings; |
551 | return NULL; | 492 | return NULL; |
552 | } | 493 | } |
553 | 494 | ||
@@ -671,9 +612,9 @@ static int hdmi_s_dv_preset(struct v4l2_subdev *sd, | |||
671 | { | 612 | { |
672 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); | 613 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); |
673 | struct device *dev = hdev->dev; | 614 | struct device *dev = hdev->dev; |
674 | const struct hdmi_preset_conf *conf; | 615 | const struct hdmi_timings *conf; |
675 | 616 | ||
676 | conf = hdmi_preset2conf(preset->preset); | 617 | conf = hdmi_preset2timings(preset->preset); |
677 | if (conf == NULL) { | 618 | if (conf == NULL) { |
678 | dev_err(dev, "preset (%u) not supported\n", preset->preset); | 619 | dev_err(dev, "preset (%u) not supported\n", preset->preset); |
679 | return -EINVAL; | 620 | return -EINVAL; |
@@ -695,21 +636,32 @@ static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd, | |||
695 | struct v4l2_mbus_framefmt *fmt) | 636 | struct v4l2_mbus_framefmt *fmt) |
696 | { | 637 | { |
697 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); | 638 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); |
698 | struct device *dev = hdev->dev; | 639 | const struct hdmi_timings *t = hdev->cur_conf; |
699 | 640 | ||
700 | dev_dbg(dev, "%s\n", __func__); | 641 | dev_dbg(hdev->dev, "%s\n", __func__); |
701 | if (!hdev->cur_conf) | 642 | if (!hdev->cur_conf) |
702 | return -EINVAL; | 643 | return -EINVAL; |
703 | *fmt = hdev->cur_conf->mbus_fmt; | 644 | memset(fmt, 0, sizeof *fmt); |
645 | fmt->width = t->hact.end - t->hact.beg; | ||
646 | fmt->height = t->vact[0].end - t->vact[0].beg; | ||
647 | fmt->code = V4L2_MBUS_FMT_FIXED; /* means RGB888 */ | ||
648 | fmt->colorspace = V4L2_COLORSPACE_SRGB; | ||
649 | if (t->interlaced) { | ||
650 | fmt->field = V4L2_FIELD_INTERLACED; | ||
651 | fmt->height *= 2; | ||
652 | } else { | ||
653 | fmt->field = V4L2_FIELD_NONE; | ||
654 | } | ||
704 | return 0; | 655 | return 0; |
705 | } | 656 | } |
706 | 657 | ||
707 | static int hdmi_enum_dv_presets(struct v4l2_subdev *sd, | 658 | static int hdmi_enum_dv_presets(struct v4l2_subdev *sd, |
708 | struct v4l2_dv_enum_preset *preset) | 659 | struct v4l2_dv_enum_preset *preset) |
709 | { | 660 | { |
710 | if (preset->index >= ARRAY_SIZE(hdmi_conf)) | 661 | if (preset->index >= ARRAY_SIZE(hdmi_timings)) |
711 | return -EINVAL; | 662 | return -EINVAL; |
712 | return v4l_fill_dv_preset_info(hdmi_conf[preset->index].preset, preset); | 663 | return v4l_fill_dv_preset_info(hdmi_timings[preset->index].preset, |
664 | preset); | ||
713 | } | 665 | } |
714 | 666 | ||
715 | static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = { | 667 | static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = { |
@@ -993,7 +945,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev) | |||
993 | strlcpy(sd->name, "s5p-hdmi", sizeof sd->name); | 945 | strlcpy(sd->name, "s5p-hdmi", sizeof sd->name); |
994 | hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET; | 946 | hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET; |
995 | /* FIXME: missing fail preset is not supported */ | 947 | /* FIXME: missing fail preset is not supported */ |
996 | hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset); | 948 | hdmi_dev->cur_conf = hdmi_preset2timings(hdmi_dev->cur_preset); |
997 | 949 | ||
998 | /* storing subdev for call that have only access to struct device */ | 950 | /* storing subdev for call that have only access to struct device */ |
999 | dev_set_drvdata(dev, sd); | 951 | dev_set_drvdata(dev, sd); |
diff --git a/drivers/media/video/s5p-tv/regs-hdmi.h b/drivers/media/video/s5p-tv/regs-hdmi.h index 33247d13e4c0..a889d1f57f28 100644 --- a/drivers/media/video/s5p-tv/regs-hdmi.h +++ b/drivers/media/video/s5p-tv/regs-hdmi.h | |||
@@ -140,6 +140,7 @@ | |||
140 | #define HDMI_MODE_MASK (3 << 0) | 140 | #define HDMI_MODE_MASK (3 << 0) |
141 | 141 | ||
142 | /* HDMI_TG_CMD */ | 142 | /* HDMI_TG_CMD */ |
143 | #define HDMI_TG_FIELD_EN (1 << 1) | ||
143 | #define HDMI_TG_EN (1 << 0) | 144 | #define HDMI_TG_EN (1 << 0) |
144 | 145 | ||
145 | #endif /* SAMSUNG_REGS_HDMI_H */ | 146 | #endif /* SAMSUNG_REGS_HDMI_H */ |