upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / s5p-tv / hdmi_drv.c
1 /*
2  * Samsung HDMI interface driver
3  *
4  * Copyright (c) 2010 Samsung Electronics
5  *
6  * Tomasz Stanislawski, t.stanislaws@samsung.com
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published
10  * by the Free Software Foundiation. either version 2 of the License,
11  * or (at your option) any later version
12  */
13
14 #include "plat/tv.h"
15 #include "hdmi.h"
16
17 #include <linux/kernel.h>
18 #include <linux/io.h>
19 #include <linux/i2c.h>
20 #include <linux/platform_device.h>
21 #include <media/v4l2-subdev.h>
22 #include <linux/module.h>
23 #include <linux/interrupt.h>
24 #include <linux/irq.h>
25 #include <linux/delay.h>
26 #include <linux/bug.h>
27
28 #include <media/v4l2-common.h>
29 #include <media/v4l2-dev.h>
30 #include <media/v4l2-device.h>
31
32 #include "regs-hdmi.h"
33 #include "hdmi_drv_priv.h"
34
35 MODULE_AUTHOR("Tomasz Stanislawski, t.stanislaws@samsung.com");
36 MODULE_DESCRIPTION("Samsung HDMI");
37 MODULE_LICENSE("GPL");
38
39 /* #define HDMI_DEFAULT_PRESET V4L2_DV_480P59_94 */
40 #define HDMI_DEFAULT_PRESET V4L2_DV_720P59_94
41 /* #define HDMI_DEFAULT_PRESET V4L2_DV_1080P60 */
42 /* #define HDMI_DEFAULT_PRESET V4L2_DV_1080P59_94 */
43
44 /* D R I V E R   I N I T I A L I Z A T I O N */
45
46 static struct platform_driver hdmi_driver;
47
48 static int __init hdmi_init(void)
49 {
50         int ret;
51         static const char banner[] __initdata = KERN_INFO \
52                 "Samsung HDMI output driver, "
53                 "(c) 2010 Samsung Electronics\n";
54         printk(banner);
55
56         ret = platform_driver_register(&hdmi_driver);
57         if (ret)
58                 printk(KERN_ERR "HDMI platform driver register failed\n");
59
60         return ret;
61 }
62 late_initcall(hdmi_init);
63
64 static void __exit hdmi_exit(void)
65 {
66         platform_driver_unregister(&hdmi_driver);
67 }
68 module_exit(hdmi_exit);
69
70 struct hdmi_device {
71         /** base address of HDMI registers */
72         void __iomem *regs;
73         /** HDMI interrupt */
74         unsigned int irq;
75         /** pointer to device parent */
76         struct device *dev;
77         /** subdev generated by HDMI device */
78         struct v4l2_subdev sd;
79         /** V4L2 device structure */
80         struct v4l2_device vdev;
81         /** subdev of HDMIPHY interface */
82         struct v4l2_subdev *phy_sd;
83         /** configuration of current graphic mode */
84         const struct hdmi_preset_conf *cur_conf;
85         /** current preset */
86         u32 cur_preset;
87         /** hdmi device plugin status */
88         bool plug_state;
89         /** mhl notification block */
90         struct notifier_block nb_mhl;
91 };
92
93 /* FIXME: this parameters should be acquired from platform data */
94 static struct i2c_board_info hdmiphy_info = {
95         I2C_BOARD_INFO("hdmiphy", 0x38),
96         /* .irq = IRQ_HDMI_I2C, */
97 };
98 static int hdmiphy_bus = 8;
99
100 static irqreturn_t hdmi_irq_handler(int irq, void *dev_data);
101
102 static const struct v4l2_subdev_ops hdmi_sd_ops;
103
104 static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset);
105
106 #define CHECK_POINT dev_err(dev, "%s:%d\n", __func__, __LINE__)
107
108 static struct hdmi_device *sd_to_hdmi_dev(struct v4l2_subdev *sd)
109 {
110         return container_of(sd, struct hdmi_device, sd);
111 }
112
113 extern int mhl_register_client(struct notifier_block *nb);
114 extern int mhl_unregister_client(struct notifier_block *nb);
115 static int hdmi_notifier_callback(struct notifier_block *this,
116                         unsigned long event, void *_data)
117 {
118         struct hdmi_device *hdmi_dev
119                 = container_of(this, struct hdmi_device, nb_mhl);
120         struct device *dev = hdmi_dev->dev;
121
122         dev_info(dev, "mhl plug-in status %d\n", (bool)event);
123         hdmi_dev->plug_state = event;
124
125         return NOTIFY_DONE;
126 }
127
128 static int __devinit hdmi_probe(struct platform_device *pdev)
129 {
130         struct device *dev = &pdev->dev;
131         struct resource *res;
132         struct i2c_adapter *phy_adapter;
133         struct hdmi_platform_data *pdata = dev->platform_data;
134         struct v4l2_subdev *sd;
135         struct hdmi_device *hdmi_dev = NULL;
136
137         int ret;
138
139         dev_info(dev, "probe start\n");
140
141         if (pdata->init) {
142                 ret = pdata->init(dev);
143                 if (ret)
144                         goto fail;
145         }
146
147         hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
148         if (!hdmi_dev) {
149                 dev_err(dev, "not enough memory.\n");
150                 ret = -ENOMEM;
151                 goto fail_init;
152         }
153
154         hdmi_dev->dev = dev;
155
156         /* mapping HDMI registers */
157         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
158         if (res == NULL) {
159                 dev_err(dev, "get memory resource failed.\n");
160                 ret = -ENXIO;
161                 goto fail_hdev;
162         }
163
164         /* TODO: add request_mem_region */
165         hdmi_dev->regs = ioremap(res->start, resource_size(res));
166         if (hdmi_dev->regs == NULL) {
167                 dev_err(dev, "register mapping failed.\n");
168                 ret = -ENXIO;
169                 goto fail_hdev;
170         }
171
172         /* acquiring HDMI interrupt */
173         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
174         if (res == NULL) {
175                 dev_err(dev, "get interrupt resource failed.\n");
176                 ret = -ENXIO;
177                 goto fail_regs;
178         }
179
180         ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev);
181         if (ret) {
182                 dev_err(dev, "request interrupt failed.\n");
183                 goto fail_regs;
184         }
185         hdmi_dev->irq = res->start;
186
187         ret = v4l2_device_register(dev, &hdmi_dev->vdev);
188         if (ret) {
189                 dev_err(dev, "could not register v4l2 device.\n");
190                 goto fail_irq;
191         }
192
193         phy_adapter = i2c_get_adapter(hdmiphy_bus);
194         if (phy_adapter == NULL) {
195                 dev_err(dev, "adapter request failed\n");
196                 ret = -ENXIO;
197                 goto fail_vdev;
198         }
199
200         hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->vdev,
201                 phy_adapter, &hdmiphy_info, NULL);
202         /* on failure or not adapter is no longer useful */
203         i2c_put_adapter(phy_adapter);
204         if (hdmi_dev->phy_sd == NULL) {
205                 dev_err(dev, "missing subdev for hdmiphy\n");
206                 ret = -ENODEV;
207                 goto fail_vdev;
208         }
209
210         sd = &hdmi_dev->sd;
211         v4l2_subdev_init(sd, &hdmi_sd_ops);
212
213         strlcpy(sd->name, hdmi_driver.driver.name, sizeof sd->name);
214         hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
215         /* FIXME: missing fail preset is not supported */
216         hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);
217
218         hdmi_dev->nb_mhl.notifier_call = hdmi_notifier_callback;
219         ret = mhl_register_client(&hdmi_dev->nb_mhl);
220         if (ret) {
221                 dev_err(dev, "could not register mhl notify callback\n");
222                 goto fail_vdev;
223         }
224
225         /* storing subdev for call that have only access to struct device */
226         dev_set_drvdata(dev, sd);
227
228         dev_info(dev, "probe sucessful\n");
229
230         return 0;
231
232 fail_vdev:
233         v4l2_device_unregister(&hdmi_dev->vdev);
234
235 fail_irq:
236         free_irq(hdmi_dev->irq, hdmi_dev);
237
238 fail_regs:
239         iounmap(hdmi_dev->regs);
240
241 fail_hdev:
242         kfree(hdmi_dev);
243
244 fail_init:
245         if (pdata->deinit)
246                 pdata->deinit(dev);
247
248 fail:
249         dev_info(dev, "probe failed\n");
250         return ret;
251 }
252
253 static int __devexit hdmi_remove(struct platform_device *pdev)
254 {
255         struct device *dev = &pdev->dev;
256         struct hdmi_platform_data *pdata = dev->platform_data;
257         struct v4l2_subdev *sd = dev_get_drvdata(dev);
258         struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
259
260         mhl_unregister_client(&hdmi_dev->nb_mhl);
261         v4l2_device_unregister(&hdmi_dev->vdev);
262         disable_irq(hdmi_dev->irq);
263         free_irq(hdmi_dev->irq, hdmi_dev);
264         iounmap(hdmi_dev->regs);
265         kfree(hdmi_dev);
266         if (pdata->deinit)
267                 pdata->deinit(dev);
268         dev_info(dev, "remove sucessful\n");
269         return 0;
270 }
271
272 static struct platform_driver hdmi_driver __refdata = {
273         .probe = hdmi_probe,
274         .remove = __devexit_p(hdmi_remove),
275         .driver = {
276                 .name = "s5p-hdmi",
277                 .owner = THIS_MODULE,
278         }
279 };
280
281 static inline
282 void hdmi_write(struct hdmi_device *hdev, u32 reg_id, u32 value)
283 {
284         writel(value, hdev->regs + reg_id);
285 }
286
287 static inline
288 void hdmi_write_mask(struct hdmi_device *hdev, u32 reg_id, u32 value, u32 mask)
289 {
290         u32 old = readl(hdev->regs + reg_id);
291         value = (value & mask) | (old & ~mask);
292         writel(value, hdev->regs + reg_id);
293 }
294
295 static inline
296 void hdmi_writeb(struct hdmi_device *hdev, u32 reg_id, u8 value)
297 {
298         writeb(value, hdev->regs + reg_id);
299 }
300
301 static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id)
302 {
303         return readl(hdev->regs + reg_id);
304 }
305
306 static irqreturn_t hdmi_irq_handler(int irq, void *dev_data)
307 {
308         struct hdmi_device *hdev = dev_data;
309         u32 intc_flag;
310         (void)irq;
311         /* TODO: add V4L2 event generation */
312
313         intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG);
314         /* clearing flags for HPD plug/unplug */
315         if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
316                 printk(KERN_INFO "unplugged\n");
317                 hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
318                         HDMI_INTC_FLAG_HPD_UNPLUG);
319         }
320         if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
321                 printk(KERN_INFO "plugged\n");
322                 hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
323                         HDMI_INTC_FLAG_HPD_PLUG);
324         }
325
326         return IRQ_HANDLED;
327 }
328
329 static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
330         struct v4l2_dv_preset *preset);
331
332 static int hdmi_s_power(struct v4l2_subdev *sd, int on)
333 {
334         struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
335         struct device *dev = hdmi_dev->dev;
336         struct hdmi_platform_data *pdata = dev->platform_data;
337
338         if (!hdmi_dev->plug_state)
339                 return -EIO;
340
341         dev_info(dev, "%s(%d)\n", __func__, on);
342
343         if (pdata->power_setup && pdata->power_setup(dev, on) != 0) {
344                 dev_err(dev, "power setup (en = %d) failed\n", on);
345                 return -EIO;
346         }
347
348         /* setting default preset if none is available */
349         if (on) {
350                 struct v4l2_dv_preset preset;
351                 preset.preset = hdmi_dev->cur_preset;
352                 return hdmi_s_dv_preset(sd, &preset);
353         } else {
354                 hdmi_dev->plug_state = false;
355         }
356
357         return 0;
358 }
359
360 static void hdmi_conf_apply(struct hdmi_device *hdev,
361         const struct hdmi_preset_conf *conf);
362 static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix);
363
364 static void hdmi_reg_init(struct hdmi_device *hdev)
365 {
366         /* enable HPD interrupts */
367         hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
368                 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
369         /* choose HDMI mode */
370         hdmi_write_mask(hdev, HDMI_MODE_SEL,
371                 HDMI_MODE_HDMI_EN | HDMI_MODE_DVI_DIS, HDMI_MODE_MASK);
372         /* XXX: choose bluescreen */
373         hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
374         /* choose bluescreen (fecal) color */
375         hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12);
376         hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34);
377         hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56);
378 }
379
380
381 static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
382         struct v4l2_dv_preset *preset)
383 {
384         struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
385         struct device *dev = hdmi_dev->dev;
386         const struct hdmi_preset_conf *conf;
387         int tries, ret;
388         dev_info(dev, "%s(preset = %u)\n", __func__, preset->preset);
389
390         conf = hdmi_preset2conf(preset->preset);
391         if (conf == NULL) {
392                 dev_err(dev, "preset (%u) not supported\n", preset->preset);
393                 return -ENXIO;
394         }
395
396         /* TODO: check if mode is supported */
397
398         /* reset hdmiphy */
399         hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
400         mdelay(10);
401         hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT,  0, HDMI_PHY_SW_RSTOUT);
402         mdelay(10);
403
404         /* configure presets */
405         ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_preset, preset);
406         if (ret) {
407                 dev_err(dev, "failed to set preset (%u)\n", preset->preset);
408                 return ret;
409         }
410
411         /* resetting HDMI core */
412         hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT,  0, HDMI_CORE_SW_RSTOUT);
413         mdelay(10);
414         hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, ~0, HDMI_CORE_SW_RSTOUT);
415         mdelay(10);
416
417         hdmi_reg_init(hdmi_dev);
418
419         /* Workaround for audio */
420         ret = hdmi_read(hdmi_dev, HDMI_MODE_SEL);
421         if (!(ret & HDMI_MODE_DVI_EN)) {
422                 struct s5p_hdmi_o_trans trans;
423                 struct s5p_hdmi_packet packet;
424
425                 memset(&trans, 0, sizeof(trans));
426                 memset(&packet, 0, sizeof(packet));
427
428                 trans.avi = 0x02;
429                 trans.mpg = 0x00;
430                 trans.spd = 0x02;
431                 trans.gcp = 0x00;
432                 trans.gmp = 0x00;
433                 trans.isrc = 0x00;
434                 trans.acp = 0x00;
435                 trans.aui = 0x02;
436                 trans.acr = 0x04;
437
438                 s5p_hdmi_set_acr(44100, packet.acr);
439                 s5p_hdmi_set_asp(packet.h_asp);
440                 s5p_hdmi_set_gcp(3, packet.gcp);
441                 s5p_hdmi_set_acp(1, packet.h_acp);
442                 s5p_hdmi_set_avi(0x00, 0x80, 0, 4, 4, 0, packet.avi);
443                 s5p_hdmi_set_spd("SAMSUNG", "S5PC210", packet.spd);
444                 s5p_hdmi_set_aui(0, 1, 44100, packet.aui);
445                 s5p_hdmi_set_mpg(packet.mpg);
446
447                 s5p_hdmi_reg_acr(hdmi_dev->regs, packet.acr);
448                 s5p_hdmi_reg_asp(hdmi_dev->regs, packet.h_asp);
449                 s5p_hdmi_reg_gcp(hdmi_dev->regs, 0, packet.gcp);
450                 s5p_hdmi_reg_acp(hdmi_dev->regs, packet.h_acp, packet.acp);
451                 s5p_hdmi_reg_infoframe(hdmi_dev->regs, 0x82, 0x2, 13, packet.avi);
452                 s5p_hdmi_reg_infoframe(hdmi_dev->regs, 0x84, 0x1, 0xa, packet.aui);
453                 s5p_hdmi_reg_infoframe(hdmi_dev->regs, 0x83, 0x1, 27, packet.spd);
454                 s5p_hdmi_reg_infoframe(hdmi_dev->regs, 0x85, 0x1, 5, packet.mpg);
455                 s5p_hdmi_reg_packet_trans(hdmi_dev->regs, &trans);
456                 s5p_hdmi_audio_init(hdmi_dev->regs, 44100, 16, 0);
457         }
458
459         /* waiting for HDMIPHY's PLL to get to steady state */
460         for (tries = 100; tries; --tries) {
461                 u32 val = hdmi_read(hdmi_dev, HDMI_PHY_STATUS);
462                 if (val & HDMI_PHY_STATUS_READY)
463                         break;
464                 mdelay(1);
465         }
466         /* steady state not achieved */
467         if (tries == 0) {
468                 dev_err(dev, "hdmiphy's pll could not reach steady state.\n");
469                 hdmi_dumpregs(hdmi_dev, "s_preset");
470                 return -EIO;
471         }
472
473         /* setting core registers */
474         hdmi_conf_apply(hdmi_dev, conf);
475         hdmi_dev->cur_conf = conf;
476         hdmi_dev->cur_preset = preset->preset;
477
478         return 0;
479 }
480
481 static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
482         struct v4l2_dv_enum_preset *preset);
483
484 static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
485           struct v4l2_mbus_framefmt *fmt)
486 {
487         struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
488         struct device *dev = hdev->dev;
489         dev_info(dev, "%s\n", __func__);
490         if (!hdev->cur_conf)
491                 return -ENXIO;
492         *fmt = hdev->cur_conf->mbus_fmt;
493         return 0;
494 }
495
496 static int hdmi_streamon(struct hdmi_device *hdev)
497 {
498         struct device *dev = hdev->dev;
499         struct hdmi_platform_data *pdata = dev->platform_data;
500         int ret = 0;
501         dev_info(dev, "%s\n", __func__);
502
503         if (pdata->stream_setup)
504                 ret = pdata->stream_setup(dev, 1);
505         if (ret) {
506                 dev_err(dev, "platform stream on failed\n");
507                 return ret;
508         }
509
510         ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 1);
511         if (ret) {
512                 dev_err(dev, "failed hdmiphy stream on.\n");
513                 return ret;
514         }
515
516         hdmi_audio_on(hdev->regs);
517
518         hdmi_write_mask(hdev, HDMI_CON_0, ~0, HDMI_EN);
519         /* XXX: enable VSYNC and BT656 synchro */
520         /* dmi_write(hdev, S5P_HDMI_TG_CMD, ~0, (1 << 3) | (1 << 4)); */
521         hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_EN);
522         hdmi_dumpregs(hdev, "streamon");
523         return 0;
524 }
525
526 static int hdmi_streamoff(struct hdmi_device *hdev)
527 {
528         struct device *dev = hdev->dev;
529         struct hdmi_platform_data *pdata = dev->platform_data;
530         int ret = 0;
531         dev_info(dev, "%s\n", __func__);
532
533         ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
534         if (ret) {
535                 dev_err(dev, "failed hdmiphy stream off.\n");
536                 return ret;
537         }
538
539         hdmi_audio_off(hdev->regs);
540
541         hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_EN);
542         hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_EN);
543         if (pdata->stream_setup)
544                 ret = pdata->stream_setup(dev, 0);
545         WARN(ret, "platform stream off failed\n");
546         hdmi_dumpregs(hdev, "streamoff");
547         return 0;
548 }
549
550 static int hdmi_s_stream(struct v4l2_subdev *sd, int enable)
551 {
552         struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
553         struct device *dev = hdev->dev;
554         dev_info(dev, "%s(%d)\n", __func__, enable);
555         if (enable)
556                 return hdmi_streamon(hdev);
557         else
558                 return hdmi_streamoff(hdev);
559         /* call stream_setup from pdata (it changes clocks) */
560         /* set bit 0 in in HDMI_CON_0 */
561         /* set bits in in HDMI_TG_CMD */
562         /* enjoy your TV */
563 }
564
565 static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
566         .s_power = hdmi_s_power,
567 };
568
569 static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
570         .s_dv_preset = hdmi_s_dv_preset,
571         .enum_dv_presets = hdmi_enum_dv_presets,
572         .g_mbus_fmt = hdmi_g_mbus_fmt,
573         .s_stream = hdmi_s_stream,
574 };
575
576 static const struct v4l2_subdev_ops hdmi_sd_ops = {
577         .core = &hdmi_sd_core_ops,
578         .video = &hdmi_sd_video_ops,
579 };
580
581 static void hdmi_conf_apply(struct hdmi_device *hdev,
582         const struct hdmi_preset_conf *conf)
583 {
584         const struct hdmi_core_regs *core = &conf->core;
585         const struct hdmi_tg_regs *tg = &conf->tg;
586         /* setting core registers */
587         hdmi_writeb(hdev, HDMI_H_BLANK_0, core->h_blank[0]);
588         hdmi_writeb(hdev, HDMI_H_BLANK_1, core->h_blank[1]);
589         hdmi_writeb(hdev, HDMI_V_BLANK_0, core->v_blank[0]);
590         hdmi_writeb(hdev, HDMI_V_BLANK_1, core->v_blank[1]);
591         hdmi_writeb(hdev, HDMI_V_BLANK_2, core->v_blank[2]);
592         hdmi_writeb(hdev, HDMI_H_V_LINE_0, core->h_v_line[0]);
593         hdmi_writeb(hdev, HDMI_H_V_LINE_1, core->h_v_line[1]);
594         hdmi_writeb(hdev, HDMI_H_V_LINE_2, core->h_v_line[2]);
595         hdmi_writeb(hdev, HDMI_VSYNC_POL, core->vsync_pol[0]);
596         hdmi_writeb(hdev, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
597         hdmi_writeb(hdev, HDMI_V_BLANK_F_0, core->v_blank_f[0]);
598         hdmi_writeb(hdev, HDMI_V_BLANK_F_1, core->v_blank_f[1]);
599         hdmi_writeb(hdev, HDMI_V_BLANK_F_2, core->v_blank_f[2]);
600         hdmi_writeb(hdev, HDMI_H_SYNC_GEN_0, core->h_sync_gen[0]);
601         hdmi_writeb(hdev, HDMI_H_SYNC_GEN_1, core->h_sync_gen[1]);
602         hdmi_writeb(hdev, HDMI_H_SYNC_GEN_2, core->h_sync_gen[2]);
603         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
604         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
605         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
606         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
607         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
608         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
609         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
610         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
611         hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
612         /* Timing generator registers */
613         hdmi_writeb(hdev, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
614         hdmi_writeb(hdev, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
615         hdmi_writeb(hdev, HDMI_TG_HACT_ST_L, tg->hact_st_l);
616         hdmi_writeb(hdev, HDMI_TG_HACT_ST_H, tg->hact_st_h);
617         hdmi_writeb(hdev, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
618         hdmi_writeb(hdev, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
619         hdmi_writeb(hdev, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
620         hdmi_writeb(hdev, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
621         hdmi_writeb(hdev, HDMI_TG_VSYNC_L, tg->vsync_l);
622         hdmi_writeb(hdev, HDMI_TG_VSYNC_H, tg->vsync_h);
623         hdmi_writeb(hdev, HDMI_TG_VSYNC2_L, tg->vsync2_l);
624         hdmi_writeb(hdev, HDMI_TG_VSYNC2_H, tg->vsync2_h);
625         hdmi_writeb(hdev, HDMI_TG_VACT_ST_L, tg->vact_st_l);
626         hdmi_writeb(hdev, HDMI_TG_VACT_ST_H, tg->vact_st_h);
627         hdmi_writeb(hdev, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
628         hdmi_writeb(hdev, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
629         hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
630         hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
631         hdmi_writeb(hdev, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
632         hdmi_writeb(hdev, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
633         hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
634         hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
635         hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
636         hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
637         hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
638         hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
639         hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
640         hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
641 }
642
643 static const struct hdmi_preset_conf hdmi_conf_480p = {
644         .core = {
645                 .h_blank = {0x8a, 0x00},
646                 .v_blank = {0x0d, 0x6a, 0x01},
647                 .h_v_line = {0x0d, 0xa2, 0x35},
648                 .vsync_pol = {0x01},
649                 .int_pro_mode = {0x00},
650                 .v_blank_f = {0x00, 0x00, 0x00},
651                 .h_sync_gen = {0x0e, 0x30, 0x11},
652                 .v_sync_gen1 = {0x0f, 0x90, 0x00},
653                 /* other don't care */
654         },
655         .tg = {
656                 0x00, /* cmd */
657                 0x5a, 0x03, /* h_fsz */
658                 0x8a, 0x00, 0xd0, 0x02, /* hact */
659                 0x0d, 0x02, /* v_fsz */
660                 0x01, 0x00, 0x33, 0x02, /* vsync */
661                 0x2d, 0x00, 0xe0, 0x01, /* vact */
662                 0x33, 0x02, /* field_chg */
663                 0x49, 0x02, /* vact_st2 */
664                 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
665                 0x01, 0x00, 0x33, 0x02, /* field top/bot */
666         },
667         .mbus_fmt = {
668                 .width = 720,
669                 .height = 480,
670                 .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
671                 .field = V4L2_FIELD_NONE,
672         },
673 };
674
675 static const struct hdmi_preset_conf hdmi_conf_720p60 = {
676         .core = {
677                 .h_blank = {0x72, 0x01},
678                 .v_blank = {0xee, 0xf2, 0x00},
679                 .h_v_line = {0xee, 0x22, 0x67},
680                 .vsync_pol = {0x00},
681                 .int_pro_mode = {0x00},
682                 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
683                 .h_sync_gen = {0x6c, 0x50, 0x02},
684                 .v_sync_gen1 = {0x0a, 0x50, 0x00},
685                 /* other don't care */
686         },
687         .tg = {
688                 0x00, /* cmd */
689                 0x72, 0x06, /* h_fsz */
690                 0x72, 0x01, 0x00, 0x05, /* hact */
691                 0xee, 0x02, /* v_fsz */
692                 0x01, 0x00, 0x33, 0x02, /* vsync */
693                 0x1e, 0x00, 0xd0, 0x02, /* vact */
694                 0x33, 0x02, /* field_chg */
695                 0x49, 0x02, /* vact_st2 */
696                 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
697                 0x01, 0x00, 0x33, 0x02, /* field top/bot */
698         },
699         .mbus_fmt = {
700                 .width = 1280,
701                 .height = 720,
702                 .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
703                 .field = V4L2_FIELD_NONE,
704         },
705 };
706
707 static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
708         .core = {
709                 .h_blank = {0xd0, 0x02},
710                 .v_blank = {0x65, 0x6c, 0x01},
711                 .h_v_line = {0x65, 0x04, 0xa5},
712                 .vsync_pol = {0x00},
713                 .int_pro_mode = {0x00},
714                 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
715                 .h_sync_gen = {0x0e, 0xea, 0x08},
716                 .v_sync_gen1 = {0x09, 0x40, 0x00},
717                 /* other don't care */
718         },
719         .tg = {
720                 0x00, /* cmd */
721                 0x98, 0x08, /* h_fsz */
722                 0x18, 0x01, 0x80, 0x07, /* hact */
723                 0x65, 0x04, /* v_fsz */
724                 0x01, 0x00, 0x33, 0x02, /* vsync */
725                 0x2d, 0x00, 0x38, 0x04, /* vact */
726                 0x33, 0x02, /* field_chg */
727                 0x49, 0x02, /* vact_st2 */
728                 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
729                 0x01, 0x00, 0x33, 0x02, /* field top/bot */
730         },
731         .mbus_fmt = {
732                 .width = 1920,
733                 .height = 1080,
734                 .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
735                 .field = V4L2_FIELD_NONE,
736         },
737 };
738
739 static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
740         .core = {
741                 .h_blank = {0x18, 0x01},
742                 .v_blank = {0x65, 0x6c, 0x01},
743                 .h_v_line = {0x65, 0x84, 0x89},
744                 .vsync_pol = {0x00},
745                 .int_pro_mode = {0x00},
746                 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
747                 .h_sync_gen = {0x56, 0x08, 0x02},
748                 .v_sync_gen1 = {0x09, 0x40, 0x00},
749                 /* other don't care */
750         },
751         .tg = {
752                 0x00, /* cmd */
753                 0x98, 0x08, /* h_fsz */
754                 0x18, 0x01, 0x80, 0x07, /* hact */
755                 0x65, 0x04, /* v_fsz */
756                 0x01, 0x00, 0x33, 0x02, /* vsync */
757                 0x2d, 0x00, 0x38, 0x04, /* vact */
758                 0x33, 0x02, /* field_chg */
759                 0x48, 0x02, /* vact_st2 */
760                 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
761                 0x01, 0x00, 0x33, 0x02, /* field top/bot */
762         },
763         .mbus_fmt = {
764                 .width = 1920,
765                 .height = 1080,
766                 .code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
767                 .field = V4L2_FIELD_NONE,
768         },
769 };
770
771 static const struct {
772         u32 preset;
773         const struct hdmi_preset_conf *conf;
774 } hdmi_conf[] = {
775         { V4L2_DV_480P59_94, &hdmi_conf_480p },
776         { V4L2_DV_720P59_94, &hdmi_conf_720p60 },
777         { V4L2_DV_1080P50, &hdmi_conf_1080p50 },
778         { V4L2_DV_1080P30, &hdmi_conf_1080p60 },
779         { V4L2_DV_1080P60, &hdmi_conf_1080p60 },
780         { V4L2_DV_1080P59_94, &hdmi_conf_1080p60 },
781 };
782
783 static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset)
784 {
785         int i;
786         for (i = 0; i < ARRAY_SIZE(hdmi_conf); ++i)
787                 if (hdmi_conf[i].preset == preset)
788                         return  hdmi_conf[i].conf;
789         return NULL;
790 }
791
792 static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
793         struct v4l2_dv_enum_preset *preset)
794 {
795         if (preset->index >= ARRAY_SIZE(hdmi_conf))
796                 return -EINVAL;
797         return v4l_fill_dv_preset_info(hdmi_conf[preset->index].preset, preset);
798 }
799
800 static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix)
801 {
802 #define DUMPREG(reg_id) \
803         printk(KERN_DEBUG "%s:" #reg_id " = %08x\n", prefix, \
804         readl(hdev->regs + reg_id))
805         printk(KERN_ERR "%s: ---- CONTROL REGISTERS ----\n", prefix);
806         DUMPREG(HDMI_INTC_FLAG);
807         DUMPREG(HDMI_INTC_CON);
808         DUMPREG(HDMI_HPD_STATUS);
809         DUMPREG(HDMI_PHY_RSTOUT);
810         DUMPREG(HDMI_PHY_VPLL);
811         DUMPREG(HDMI_PHY_CMU);
812         DUMPREG(HDMI_CORE_RSTOUT);
813
814         printk(KERN_ERR "%s: ---- CORE REGISTERS ----\n", prefix);
815         DUMPREG(HDMI_CON_0);
816         DUMPREG(HDMI_CON_1);
817         DUMPREG(HDMI_CON_2);
818         DUMPREG(HDMI_SYS_STATUS);
819         DUMPREG(HDMI_PHY_STATUS);
820         DUMPREG(HDMI_STATUS_EN);
821         DUMPREG(HDMI_HPD);
822         DUMPREG(HDMI_MODE_SEL);
823         DUMPREG(HDMI_HPD_GEN);
824         DUMPREG(HDMI_DC_CONTROL);
825         DUMPREG(HDMI_VIDEO_PATTERN_GEN);
826
827         printk(KERN_ERR "%s: ---- CORE SYNC REGISTERS ----\n", prefix);
828         DUMPREG(HDMI_H_BLANK_0);
829         DUMPREG(HDMI_H_BLANK_1);
830         DUMPREG(HDMI_V_BLANK_0);
831         DUMPREG(HDMI_V_BLANK_1);
832         DUMPREG(HDMI_V_BLANK_2);
833         DUMPREG(HDMI_H_V_LINE_0);
834         DUMPREG(HDMI_H_V_LINE_1);
835         DUMPREG(HDMI_H_V_LINE_2);
836         DUMPREG(HDMI_VSYNC_POL);
837         DUMPREG(HDMI_INT_PRO_MODE);
838         DUMPREG(HDMI_V_BLANK_F_0);
839         DUMPREG(HDMI_V_BLANK_F_1);
840         DUMPREG(HDMI_V_BLANK_F_2);
841         DUMPREG(HDMI_H_SYNC_GEN_0);
842         DUMPREG(HDMI_H_SYNC_GEN_1);
843         DUMPREG(HDMI_H_SYNC_GEN_2);
844         DUMPREG(HDMI_V_SYNC_GEN_1_0);
845         DUMPREG(HDMI_V_SYNC_GEN_1_1);
846         DUMPREG(HDMI_V_SYNC_GEN_1_2);
847         DUMPREG(HDMI_V_SYNC_GEN_2_0);
848         DUMPREG(HDMI_V_SYNC_GEN_2_1);
849         DUMPREG(HDMI_V_SYNC_GEN_2_2);
850         DUMPREG(HDMI_V_SYNC_GEN_3_0);
851         DUMPREG(HDMI_V_SYNC_GEN_3_1);
852         DUMPREG(HDMI_V_SYNC_GEN_3_2);
853
854         printk(KERN_ERR "%s: ---- TG REGISTERS ----\n", prefix);
855         DUMPREG(HDMI_TG_CMD);
856         DUMPREG(HDMI_TG_H_FSZ_L);
857         DUMPREG(HDMI_TG_H_FSZ_H);
858         DUMPREG(HDMI_TG_HACT_ST_L);
859         DUMPREG(HDMI_TG_HACT_ST_H);
860         DUMPREG(HDMI_TG_HACT_SZ_L);
861         DUMPREG(HDMI_TG_HACT_SZ_H);
862         DUMPREG(HDMI_TG_V_FSZ_L);
863         DUMPREG(HDMI_TG_V_FSZ_H);
864         DUMPREG(HDMI_TG_VSYNC_L);
865         DUMPREG(HDMI_TG_VSYNC_H);
866         DUMPREG(HDMI_TG_VSYNC2_L);
867         DUMPREG(HDMI_TG_VSYNC2_H);
868         DUMPREG(HDMI_TG_VACT_ST_L);
869         DUMPREG(HDMI_TG_VACT_ST_H);
870         DUMPREG(HDMI_TG_VACT_SZ_L);
871         DUMPREG(HDMI_TG_VACT_SZ_H);
872         DUMPREG(HDMI_TG_FIELD_CHG_L);
873         DUMPREG(HDMI_TG_FIELD_CHG_H);
874         DUMPREG(HDMI_TG_VACT_ST2_L);
875         DUMPREG(HDMI_TG_VACT_ST2_H);
876         DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
877         DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
878         DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
879         DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
880         DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
881         DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
882         DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
883         DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
884 #undef DUMPREG
885 }
886