aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-02-21 19:17:11 -0500
committerDave Airlie <airlied@redhat.com>2013-02-21 19:18:04 -0500
commitc976cb37a95a8dcaf23d04d6487fbacc33d3c913 (patch)
tree12afc62084d55f2f06db9e0ef8636758bf94d61b /drivers/gpu
parent907a773ba365daa9f86c6bb8cb11ddbf9b11a3d1 (diff)
parent95fc633735331b3404d0ae65a3bb08d02640dbd0 (diff)
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
The summary: . Add display mode check operaion to mixer driver - Mixer IP also can put certain restrictions on the proposed display modes and these restrictions need to be considered during mode negotiation, which happens immediately after edid parsing. . Set correct mode for range of resolutions - With this patch, the mixer driver could find the correct mode for the range of resolutions upto 1080 vertical lines. . Support extra resolution for hdmi - This patch programs the core and timing generator registers using the timing data provided in drm_display_mode without hard-coded configurations. So this patch adds additional PHY configs to allow us to support more permissible resolutions and refresh rates. . Add device tree support for g2d - This patch adds just the compatible string for exynos5250 SoC so that with device tree enabling, this driver can be probed. . And bug fixes and code cleanups. * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: drm/exynos: Add device tree based discovery support for G2D drm/exynos: hdmi: support extra resolutions using drm_display_mode timings drm/exynos: mixer: set correct mode for range of resolutions drm/exynos: implement display-mode-check callback in mixer driver drm/exynos: add display-mode-check operation to exynos_mixer_ops struct drm/exynos: release resources properly when fb creation is failed. drm/exynos: fix wrong pointer access at vm close. drm/exynos: Add missing braces around sizeof drm/exynos: consider exception case to fb handle creation drm/exynos: fix iommu address allocation order
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c55
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c33
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.h5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_iommu.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c1035
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c34
8 files changed, 490 insertions, 698 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 294c0513f587..0e04f4ea441f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -99,6 +99,10 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
99 99
100 DRM_DEBUG_KMS("%s\n", __FILE__); 100 DRM_DEBUG_KMS("%s\n", __FILE__);
101 101
102 /* This fb should have only one gem object. */
103 if (WARN_ON(exynos_fb->buf_cnt != 1))
104 return -EINVAL;
105
102 return drm_gem_handle_create(file_priv, 106 return drm_gem_handle_create(file_priv,
103 &exynos_fb->exynos_gem_obj[0]->base, handle); 107 &exynos_fb->exynos_gem_obj[0]->base, handle);
104} 108}
@@ -217,23 +221,25 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
217 struct drm_mode_fb_cmd2 *mode_cmd) 221 struct drm_mode_fb_cmd2 *mode_cmd)
218{ 222{
219 struct drm_gem_object *obj; 223 struct drm_gem_object *obj;
224 struct exynos_drm_gem_obj *exynos_gem_obj;
220 struct exynos_drm_fb *exynos_fb; 225 struct exynos_drm_fb *exynos_fb;
221 int i, ret; 226 int i, ret;
222 227
223 DRM_DEBUG_KMS("%s\n", __FILE__); 228 DRM_DEBUG_KMS("%s\n", __FILE__);
224 229
225 obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
226 if (!obj) {
227 DRM_ERROR("failed to lookup gem object\n");
228 return ERR_PTR(-ENOENT);
229 }
230
231 exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); 230 exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
232 if (!exynos_fb) { 231 if (!exynos_fb) {
233 DRM_ERROR("failed to allocate exynos drm framebuffer\n"); 232 DRM_ERROR("failed to allocate exynos drm framebuffer\n");
234 return ERR_PTR(-ENOMEM); 233 return ERR_PTR(-ENOMEM);
235 } 234 }
236 235
236 obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
237 if (!obj) {
238 DRM_ERROR("failed to lookup gem object\n");
239 ret = -ENOENT;
240 goto err_free;
241 }
242
237 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); 243 drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
238 exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); 244 exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
239 exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); 245 exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd);
@@ -241,43 +247,44 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
241 DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); 247 DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);
242 248
243 for (i = 1; i < exynos_fb->buf_cnt; i++) { 249 for (i = 1; i < exynos_fb->buf_cnt; i++) {
244 struct exynos_drm_gem_obj *exynos_gem_obj;
245 int ret;
246
247 obj = drm_gem_object_lookup(dev, file_priv, 250 obj = drm_gem_object_lookup(dev, file_priv,
248 mode_cmd->handles[i]); 251 mode_cmd->handles[i]);
249 if (!obj) { 252 if (!obj) {
250 DRM_ERROR("failed to lookup gem object\n"); 253 DRM_ERROR("failed to lookup gem object\n");
251 kfree(exynos_fb); 254 ret = -ENOENT;
252 return ERR_PTR(-ENOENT); 255 exynos_fb->buf_cnt = i;
256 goto err_unreference;
253 } 257 }
254 258
255 exynos_gem_obj = to_exynos_gem_obj(obj); 259 exynos_gem_obj = to_exynos_gem_obj(obj);
260 exynos_fb->exynos_gem_obj[i] = exynos_gem_obj;
256 261
257 ret = check_fb_gem_memory_type(dev, exynos_gem_obj); 262 ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
258 if (ret < 0) { 263 if (ret < 0) {
259 DRM_ERROR("cannot use this gem memory type for fb.\n"); 264 DRM_ERROR("cannot use this gem memory type for fb.\n");
260 kfree(exynos_fb); 265 goto err_unreference;
261 return ERR_PTR(ret);
262 } 266 }
263
264 exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
265 } 267 }
266 268
267 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); 269 ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
268 if (ret) { 270 if (ret) {
269 for (i = 0; i < exynos_fb->buf_cnt; i++) { 271 DRM_ERROR("failed to init framebuffer.\n");
270 struct exynos_drm_gem_obj *gem_obj; 272 goto err_unreference;
271
272 gem_obj = exynos_fb->exynos_gem_obj[i];
273 drm_gem_object_unreference_unlocked(&gem_obj->base);
274 }
275
276 kfree(exynos_fb);
277 return ERR_PTR(ret);
278 } 273 }
279 274
280 return &exynos_fb->fb; 275 return &exynos_fb->fb;
276
277err_unreference:
278 for (i = 0; i < exynos_fb->buf_cnt; i++) {
279 struct drm_gem_object *obj;
280
281 obj = &exynos_fb->exynos_gem_obj[i]->base;
282 if (obj)
283 drm_gem_object_unreference_unlocked(obj);
284 }
285err_free:
286 kfree(exynos_fb);
287 return ERR_PTR(ret);
281} 288}
282 289
283struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, 290struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 9a4c08e7453c..0fcfbe4660bb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -19,6 +19,7 @@
19#include <linux/workqueue.h> 19#include <linux/workqueue.h>
20#include <linux/dma-mapping.h> 20#include <linux/dma-mapping.h>
21#include <linux/dma-attrs.h> 21#include <linux/dma-attrs.h>
22#include <linux/of.h>
22 23
23#include <drm/drmP.h> 24#include <drm/drmP.h>
24#include <drm/exynos_drm.h> 25#include <drm/exynos_drm.h>
@@ -429,7 +430,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
429 430
430 g2d_userptr->pages = pages; 431 g2d_userptr->pages = pages;
431 432
432 sgt = kzalloc(sizeof *sgt, GFP_KERNEL); 433 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
433 if (!sgt) { 434 if (!sgt) {
434 DRM_ERROR("failed to allocate sg table.\n"); 435 DRM_ERROR("failed to allocate sg table.\n");
435 ret = -ENOMEM; 436 ret = -ENOMEM;
@@ -1240,6 +1241,14 @@ static int g2d_resume(struct device *dev)
1240 1241
1241static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); 1242static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
1242 1243
1244#ifdef CONFIG_OF
1245static const struct of_device_id exynos_g2d_match[] = {
1246 { .compatible = "samsung,exynos5250-g2d" },
1247 {},
1248};
1249MODULE_DEVICE_TABLE(of, exynos_g2d_match);
1250#endif
1251
1243struct platform_driver g2d_driver = { 1252struct platform_driver g2d_driver = {
1244 .probe = g2d_probe, 1253 .probe = g2d_probe,
1245 .remove = g2d_remove, 1254 .remove = g2d_remove,
@@ -1247,5 +1256,6 @@ struct platform_driver g2d_driver = {
1247 .name = "s5p-g2d", 1256 .name = "s5p-g2d",
1248 .owner = THIS_MODULE, 1257 .owner = THIS_MODULE,
1249 .pm = &g2d_pm_ops, 1258 .pm = &g2d_pm_ops,
1259 .of_match_table = of_match_ptr(exynos_g2d_match),
1250 }, 1260 },
1251}; 1261};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 473180776528..67e17ce112b6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -329,17 +329,11 @@ static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev,
329{ 329{
330 struct drm_file *file_priv; 330 struct drm_file *file_priv;
331 331
332 mutex_lock(&drm_dev->struct_mutex);
333
334 /* find current process's drm_file from filelist. */ 332 /* find current process's drm_file from filelist. */
335 list_for_each_entry(file_priv, &drm_dev->filelist, lhead) { 333 list_for_each_entry(file_priv, &drm_dev->filelist, lhead)
336 if (file_priv->filp == filp) { 334 if (file_priv->filp == filp)
337 mutex_unlock(&drm_dev->struct_mutex);
338 return file_priv; 335 return file_priv;
339 }
340 }
341 336
342 mutex_unlock(&drm_dev->struct_mutex);
343 WARN_ON(1); 337 WARN_ON(1);
344 338
345 return ERR_PTR(-EFAULT); 339 return ERR_PTR(-EFAULT);
@@ -400,9 +394,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
400 */ 394 */
401 drm_gem_object_reference(obj); 395 drm_gem_object_reference(obj);
402 396
403 mutex_lock(&drm_dev->struct_mutex);
404 drm_vm_open_locked(drm_dev, vma); 397 drm_vm_open_locked(drm_dev, vma);
405 mutex_unlock(&drm_dev->struct_mutex);
406 398
407 return 0; 399 return 0;
408} 400}
@@ -432,6 +424,16 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
432 } 424 }
433 425
434 /* 426 /*
427 * We have to use gem object and its fops for specific mmaper,
428 * but vm_mmap() can deliver only filp. So we have to change
429 * filp->f_op and filp->private_data temporarily, then restore
430 * again. So it is important to keep lock until restoration the
431 * settings to prevent others from misuse of filp->f_op or
432 * filp->private_data.
433 */
434 mutex_lock(&dev->struct_mutex);
435
436 /*
435 * Set specific mmper's fops. And it will be restored by 437 * Set specific mmper's fops. And it will be restored by
436 * exynos_drm_gem_mmap_buffer to dev->driver->fops. 438 * exynos_drm_gem_mmap_buffer to dev->driver->fops.
437 * This is used to call specific mapper temporarily. 439 * This is used to call specific mapper temporarily.
@@ -448,13 +450,20 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
448 addr = vm_mmap(file_priv->filp, 0, args->size, 450 addr = vm_mmap(file_priv->filp, 0, args->size,
449 PROT_READ | PROT_WRITE, MAP_SHARED, 0); 451 PROT_READ | PROT_WRITE, MAP_SHARED, 0);
450 452
451 drm_gem_object_unreference_unlocked(obj); 453 drm_gem_object_unreference(obj);
452 454
453 if (IS_ERR((void *)addr)) { 455 if (IS_ERR((void *)addr)) {
454 file_priv->filp->private_data = file_priv; 456 /* check filp->f_op, filp->private_data are restored */
457 if (file_priv->filp->f_op == &exynos_drm_gem_fops) {
458 file_priv->filp->f_op = fops_get(dev->driver->fops);
459 file_priv->filp->private_data = file_priv;
460 }
461 mutex_unlock(&dev->struct_mutex);
455 return PTR_ERR((void *)addr); 462 return PTR_ERR((void *)addr);
456 } 463 }
457 464
465 mutex_unlock(&dev->struct_mutex);
466
458 args->mapped = addr; 467 args->mapped = addr;
459 468
460 DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped); 469 DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 28644539b305..7c27df03c9ff 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -124,9 +124,21 @@ static struct edid *drm_hdmi_get_edid(struct device *dev,
124static int drm_hdmi_check_timing(struct device *dev, void *timing) 124static int drm_hdmi_check_timing(struct device *dev, void *timing)
125{ 125{
126 struct drm_hdmi_context *ctx = to_context(dev); 126 struct drm_hdmi_context *ctx = to_context(dev);
127 int ret = 0;
127 128
128 DRM_DEBUG_KMS("%s\n", __FILE__); 129 DRM_DEBUG_KMS("%s\n", __FILE__);
129 130
131 /*
132 * Both, mixer and hdmi should be able to handle the requested mode.
133 * If any of the two fails, return mode as BAD.
134 */
135
136 if (mixer_ops && mixer_ops->check_timing)
137 ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing);
138
139 if (ret)
140 return ret;
141
130 if (hdmi_ops && hdmi_ops->check_timing) 142 if (hdmi_ops && hdmi_ops->check_timing)
131 return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing); 143 return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
132 144
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index d80516fc9ed7..b7faa3662307 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -32,7 +32,7 @@ struct exynos_hdmi_ops {
32 bool (*is_connected)(void *ctx); 32 bool (*is_connected)(void *ctx);
33 struct edid *(*get_edid)(void *ctx, 33 struct edid *(*get_edid)(void *ctx,
34 struct drm_connector *connector); 34 struct drm_connector *connector);
35 int (*check_timing)(void *ctx, void *timing); 35 int (*check_timing)(void *ctx, struct fb_videomode *timing);
36 int (*power_on)(void *ctx, int mode); 36 int (*power_on)(void *ctx, int mode);
37 37
38 /* manager */ 38 /* manager */
@@ -58,6 +58,9 @@ struct exynos_mixer_ops {
58 void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay); 58 void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
59 void (*win_commit)(void *ctx, int zpos); 59 void (*win_commit)(void *ctx, int zpos);
60 void (*win_disable)(void *ctx, int zpos); 60 void (*win_disable)(void *ctx, int zpos);
61
62 /* display */
63 int (*check_timing)(void *ctx, struct fb_videomode *timing);
61}; 64};
62 65
63void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx); 66void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
index 53b7deea8ab7..598e60f57d4b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
@@ -14,7 +14,7 @@
14 14
15#define EXYNOS_DEV_ADDR_START 0x20000000 15#define EXYNOS_DEV_ADDR_START 0x20000000
16#define EXYNOS_DEV_ADDR_SIZE 0x40000000 16#define EXYNOS_DEV_ADDR_SIZE 0x40000000
17#define EXYNOS_DEV_ADDR_ORDER 0x4 17#define EXYNOS_DEV_ADDR_ORDER 0x0
18 18
19#ifdef CONFIG_DRM_EXYNOS_IOMMU 19#ifdef CONFIG_DRM_EXYNOS_IOMMU
20 20
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index fbab3c468603..6d63f9090f94 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -87,6 +87,73 @@ struct hdmi_resources {
87 int regul_count; 87 int regul_count;
88}; 88};
89 89
90struct hdmi_tg_regs {
91 u8 cmd[1];
92 u8 h_fsz[2];
93 u8 hact_st[2];
94 u8 hact_sz[2];
95 u8 v_fsz[2];
96 u8 vsync[2];
97 u8 vsync2[2];
98 u8 vact_st[2];
99 u8 vact_sz[2];
100 u8 field_chg[2];
101 u8 vact_st2[2];
102 u8 vact_st3[2];
103 u8 vact_st4[2];
104 u8 vsync_top_hdmi[2];
105 u8 vsync_bot_hdmi[2];
106 u8 field_top_hdmi[2];
107 u8 field_bot_hdmi[2];
108 u8 tg_3d[1];
109};
110
111struct hdmi_core_regs {
112 u8 h_blank[2];
113 u8 v2_blank[2];
114 u8 v1_blank[2];
115 u8 v_line[2];
116 u8 h_line[2];
117 u8 hsync_pol[1];
118 u8 vsync_pol[1];
119 u8 int_pro_mode[1];
120 u8 v_blank_f0[2];
121 u8 v_blank_f1[2];
122 u8 h_sync_start[2];
123 u8 h_sync_end[2];
124 u8 v_sync_line_bef_2[2];
125 u8 v_sync_line_bef_1[2];
126 u8 v_sync_line_aft_2[2];
127 u8 v_sync_line_aft_1[2];
128 u8 v_sync_line_aft_pxl_2[2];
129 u8 v_sync_line_aft_pxl_1[2];
130 u8 v_blank_f2[2]; /* for 3D mode */
131 u8 v_blank_f3[2]; /* for 3D mode */
132 u8 v_blank_f4[2]; /* for 3D mode */
133 u8 v_blank_f5[2]; /* for 3D mode */
134 u8 v_sync_line_aft_3[2];
135 u8 v_sync_line_aft_4[2];
136 u8 v_sync_line_aft_5[2];
137 u8 v_sync_line_aft_6[2];
138 u8 v_sync_line_aft_pxl_3[2];
139 u8 v_sync_line_aft_pxl_4[2];
140 u8 v_sync_line_aft_pxl_5[2];
141 u8 v_sync_line_aft_pxl_6[2];
142 u8 vact_space_1[2];
143 u8 vact_space_2[2];
144 u8 vact_space_3[2];
145 u8 vact_space_4[2];
146 u8 vact_space_5[2];
147 u8 vact_space_6[2];
148};
149
150struct hdmi_v14_conf {
151 int pixel_clock;
152 struct hdmi_core_regs core;
153 struct hdmi_tg_regs tg;
154 int cea_video_id;
155};
156
90struct hdmi_context { 157struct hdmi_context {
91 struct device *dev; 158 struct device *dev;
92 struct drm_device *drm_dev; 159 struct drm_device *drm_dev;
@@ -104,6 +171,7 @@ struct hdmi_context {
104 171
105 /* current hdmiphy conf index */ 172 /* current hdmiphy conf index */
106 int cur_conf; 173 int cur_conf;
174 struct hdmi_v14_conf mode_conf;
107 175
108 struct hdmi_resources res; 176 struct hdmi_resources res;
109 177
@@ -392,586 +460,132 @@ static const struct hdmi_v13_conf hdmi_v13_confs[] = {
392}; 460};
393 461
394/* HDMI Version 1.4 */ 462/* HDMI Version 1.4 */
395static const u8 hdmiphy_conf27_027[32] = { 463struct hdmiphy_config {
396 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08, 464 int pixel_clock;
397 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, 465 u8 conf[32];
398 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
399 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
400};
401
402static const u8 hdmiphy_conf74_176[32] = {
403 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08,
404 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80,
405 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
406 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
407};
408
409static const u8 hdmiphy_conf74_25[32] = {
410 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
411 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
412 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
413 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
414};
415
416static const u8 hdmiphy_conf148_5[32] = {
417 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
418 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
419 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
420 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
421};
422
423struct hdmi_tg_regs {
424 u8 cmd;
425 u8 h_fsz_l;
426 u8 h_fsz_h;
427 u8 hact_st_l;
428 u8 hact_st_h;
429 u8 hact_sz_l;
430 u8 hact_sz_h;
431 u8 v_fsz_l;
432 u8 v_fsz_h;
433 u8 vsync_l;
434 u8 vsync_h;
435 u8 vsync2_l;
436 u8 vsync2_h;
437 u8 vact_st_l;
438 u8 vact_st_h;
439 u8 vact_sz_l;
440 u8 vact_sz_h;
441 u8 field_chg_l;
442 u8 field_chg_h;
443 u8 vact_st2_l;
444 u8 vact_st2_h;
445 u8 vact_st3_l;
446 u8 vact_st3_h;
447 u8 vact_st4_l;
448 u8 vact_st4_h;
449 u8 vsync_top_hdmi_l;
450 u8 vsync_top_hdmi_h;
451 u8 vsync_bot_hdmi_l;
452 u8 vsync_bot_hdmi_h;
453 u8 field_top_hdmi_l;
454 u8 field_top_hdmi_h;
455 u8 field_bot_hdmi_l;
456 u8 field_bot_hdmi_h;
457 u8 tg_3d;
458};
459
460struct hdmi_core_regs {
461 u8 h_blank[2];
462 u8 v2_blank[2];
463 u8 v1_blank[2];
464 u8 v_line[2];
465 u8 h_line[2];
466 u8 hsync_pol[1];
467 u8 vsync_pol[1];
468 u8 int_pro_mode[1];
469 u8 v_blank_f0[2];
470 u8 v_blank_f1[2];
471 u8 h_sync_start[2];
472 u8 h_sync_end[2];
473 u8 v_sync_line_bef_2[2];
474 u8 v_sync_line_bef_1[2];
475 u8 v_sync_line_aft_2[2];
476 u8 v_sync_line_aft_1[2];
477 u8 v_sync_line_aft_pxl_2[2];
478 u8 v_sync_line_aft_pxl_1[2];
479 u8 v_blank_f2[2]; /* for 3D mode */
480 u8 v_blank_f3[2]; /* for 3D mode */
481 u8 v_blank_f4[2]; /* for 3D mode */
482 u8 v_blank_f5[2]; /* for 3D mode */
483 u8 v_sync_line_aft_3[2];
484 u8 v_sync_line_aft_4[2];
485 u8 v_sync_line_aft_5[2];
486 u8 v_sync_line_aft_6[2];
487 u8 v_sync_line_aft_pxl_3[2];
488 u8 v_sync_line_aft_pxl_4[2];
489 u8 v_sync_line_aft_pxl_5[2];
490 u8 v_sync_line_aft_pxl_6[2];
491 u8 vact_space_1[2];
492 u8 vact_space_2[2];
493 u8 vact_space_3[2];
494 u8 vact_space_4[2];
495 u8 vact_space_5[2];
496 u8 vact_space_6[2];
497};
498
499struct hdmi_preset_conf {
500 struct hdmi_core_regs core;
501 struct hdmi_tg_regs tg;
502};
503
504struct hdmi_conf {
505 int width;
506 int height;
507 int vrefresh;
508 bool interlace;
509 int cea_video_id;
510 const u8 *hdmiphy_data;
511 const struct hdmi_preset_conf *conf;
512};
513
514static const struct hdmi_preset_conf hdmi_conf_480p60 = {
515 .core = {
516 .h_blank = {0x8a, 0x00},
517 .v2_blank = {0x0d, 0x02},
518 .v1_blank = {0x2d, 0x00},
519 .v_line = {0x0d, 0x02},
520 .h_line = {0x5a, 0x03},
521 .hsync_pol = {0x01},
522 .vsync_pol = {0x01},
523 .int_pro_mode = {0x00},
524 .v_blank_f0 = {0xff, 0xff},
525 .v_blank_f1 = {0xff, 0xff},
526 .h_sync_start = {0x0e, 0x00},
527 .h_sync_end = {0x4c, 0x00},
528 .v_sync_line_bef_2 = {0x0f, 0x00},
529 .v_sync_line_bef_1 = {0x09, 0x00},
530 .v_sync_line_aft_2 = {0xff, 0xff},
531 .v_sync_line_aft_1 = {0xff, 0xff},
532 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
533 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
534 .v_blank_f2 = {0xff, 0xff},
535 .v_blank_f3 = {0xff, 0xff},
536 .v_blank_f4 = {0xff, 0xff},
537 .v_blank_f5 = {0xff, 0xff},
538 .v_sync_line_aft_3 = {0xff, 0xff},
539 .v_sync_line_aft_4 = {0xff, 0xff},
540 .v_sync_line_aft_5 = {0xff, 0xff},
541 .v_sync_line_aft_6 = {0xff, 0xff},
542 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
543 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
544 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
545 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
546 .vact_space_1 = {0xff, 0xff},
547 .vact_space_2 = {0xff, 0xff},
548 .vact_space_3 = {0xff, 0xff},
549 .vact_space_4 = {0xff, 0xff},
550 .vact_space_5 = {0xff, 0xff},
551 .vact_space_6 = {0xff, 0xff},
552 /* other don't care */
553 },
554 .tg = {
555 0x00, /* cmd */
556 0x5a, 0x03, /* h_fsz */
557 0x8a, 0x00, 0xd0, 0x02, /* hact */
558 0x0d, 0x02, /* v_fsz */
559 0x01, 0x00, 0x33, 0x02, /* vsync */
560 0x2d, 0x00, 0xe0, 0x01, /* vact */
561 0x33, 0x02, /* field_chg */
562 0x48, 0x02, /* vact_st2 */
563 0x00, 0x00, /* vact_st3 */
564 0x00, 0x00, /* vact_st4 */
565 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
566 0x01, 0x00, 0x33, 0x02, /* field top/bot */
567 0x00, /* 3d FP */
568 },
569}; 466};
570 467
571static const struct hdmi_preset_conf hdmi_conf_720p50 = { 468/* list of all required phy config settings */
572 .core = { 469static const struct hdmiphy_config hdmiphy_v14_configs[] = {
573 .h_blank = {0xbc, 0x02}, 470 {
574 .v2_blank = {0xee, 0x02}, 471 .pixel_clock = 25200000,
575 .v1_blank = {0x1e, 0x00}, 472 .conf = {
576 .v_line = {0xee, 0x02}, 473 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
577 .h_line = {0xbc, 0x07}, 474 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
578 .hsync_pol = {0x00}, 475 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
579 .vsync_pol = {0x00}, 476 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
580 .int_pro_mode = {0x00}, 477 },
581 .v_blank_f0 = {0xff, 0xff},
582 .v_blank_f1 = {0xff, 0xff},
583 .h_sync_start = {0xb6, 0x01},
584 .h_sync_end = {0xde, 0x01},
585 .v_sync_line_bef_2 = {0x0a, 0x00},
586 .v_sync_line_bef_1 = {0x05, 0x00},
587 .v_sync_line_aft_2 = {0xff, 0xff},
588 .v_sync_line_aft_1 = {0xff, 0xff},
589 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
590 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
591 .v_blank_f2 = {0xff, 0xff},
592 .v_blank_f3 = {0xff, 0xff},
593 .v_blank_f4 = {0xff, 0xff},
594 .v_blank_f5 = {0xff, 0xff},
595 .v_sync_line_aft_3 = {0xff, 0xff},
596 .v_sync_line_aft_4 = {0xff, 0xff},
597 .v_sync_line_aft_5 = {0xff, 0xff},
598 .v_sync_line_aft_6 = {0xff, 0xff},
599 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
600 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
601 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
602 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
603 .vact_space_1 = {0xff, 0xff},
604 .vact_space_2 = {0xff, 0xff},
605 .vact_space_3 = {0xff, 0xff},
606 .vact_space_4 = {0xff, 0xff},
607 .vact_space_5 = {0xff, 0xff},
608 .vact_space_6 = {0xff, 0xff},
609 /* other don't care */
610 },
611 .tg = {
612 0x00, /* cmd */
613 0xbc, 0x07, /* h_fsz */
614 0xbc, 0x02, 0x00, 0x05, /* hact */
615 0xee, 0x02, /* v_fsz */
616 0x01, 0x00, 0x33, 0x02, /* vsync */
617 0x1e, 0x00, 0xd0, 0x02, /* vact */
618 0x33, 0x02, /* field_chg */
619 0x48, 0x02, /* vact_st2 */
620 0x00, 0x00, /* vact_st3 */
621 0x00, 0x00, /* vact_st4 */
622 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
623 0x01, 0x00, 0x33, 0x02, /* field top/bot */
624 0x00, /* 3d FP */
625 }, 478 },
626}; 479 {
627 480 .pixel_clock = 27000000,
628static const struct hdmi_preset_conf hdmi_conf_720p60 = { 481 .conf = {
629 .core = { 482 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
630 .h_blank = {0x72, 0x01}, 483 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
631 .v2_blank = {0xee, 0x02}, 484 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
632 .v1_blank = {0x1e, 0x00}, 485 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
633 .v_line = {0xee, 0x02}, 486 },
634 .h_line = {0x72, 0x06},
635 .hsync_pol = {0x00},
636 .vsync_pol = {0x00},
637 .int_pro_mode = {0x00},
638 .v_blank_f0 = {0xff, 0xff},
639 .v_blank_f1 = {0xff, 0xff},
640 .h_sync_start = {0x6c, 0x00},
641 .h_sync_end = {0x94, 0x00},
642 .v_sync_line_bef_2 = {0x0a, 0x00},
643 .v_sync_line_bef_1 = {0x05, 0x00},
644 .v_sync_line_aft_2 = {0xff, 0xff},
645 .v_sync_line_aft_1 = {0xff, 0xff},
646 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
647 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
648 .v_blank_f2 = {0xff, 0xff},
649 .v_blank_f3 = {0xff, 0xff},
650 .v_blank_f4 = {0xff, 0xff},
651 .v_blank_f5 = {0xff, 0xff},
652 .v_sync_line_aft_3 = {0xff, 0xff},
653 .v_sync_line_aft_4 = {0xff, 0xff},
654 .v_sync_line_aft_5 = {0xff, 0xff},
655 .v_sync_line_aft_6 = {0xff, 0xff},
656 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
657 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
658 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
659 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
660 .vact_space_1 = {0xff, 0xff},
661 .vact_space_2 = {0xff, 0xff},
662 .vact_space_3 = {0xff, 0xff},
663 .vact_space_4 = {0xff, 0xff},
664 .vact_space_5 = {0xff, 0xff},
665 .vact_space_6 = {0xff, 0xff},
666 /* other don't care */
667 }, 487 },
668 .tg = { 488 {
669 0x00, /* cmd */ 489 .pixel_clock = 27027000,
670 0x72, 0x06, /* h_fsz */ 490 .conf = {
671 0x72, 0x01, 0x00, 0x05, /* hact */ 491 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
672 0xee, 0x02, /* v_fsz */ 492 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
673 0x01, 0x00, 0x33, 0x02, /* vsync */ 493 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
674 0x1e, 0x00, 0xd0, 0x02, /* vact */ 494 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
675 0x33, 0x02, /* field_chg */ 495 },
676 0x48, 0x02, /* vact_st2 */
677 0x00, 0x00, /* vact_st3 */
678 0x00, 0x00, /* vact_st4 */
679 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
680 0x01, 0x00, 0x33, 0x02, /* field top/bot */
681 0x00, /* 3d FP */
682 }, 496 },
683}; 497 {
684 498 .pixel_clock = 36000000,
685static const struct hdmi_preset_conf hdmi_conf_1080i50 = { 499 .conf = {
686 .core = { 500 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
687 .h_blank = {0xd0, 0x02}, 501 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
688 .v2_blank = {0x32, 0x02}, 502 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
689 .v1_blank = {0x16, 0x00}, 503 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
690 .v_line = {0x65, 0x04}, 504 },
691 .h_line = {0x50, 0x0a},
692 .hsync_pol = {0x00},
693 .vsync_pol = {0x00},
694 .int_pro_mode = {0x01},
695 .v_blank_f0 = {0x49, 0x02},
696 .v_blank_f1 = {0x65, 0x04},
697 .h_sync_start = {0x0e, 0x02},
698 .h_sync_end = {0x3a, 0x02},
699 .v_sync_line_bef_2 = {0x07, 0x00},
700 .v_sync_line_bef_1 = {0x02, 0x00},
701 .v_sync_line_aft_2 = {0x39, 0x02},
702 .v_sync_line_aft_1 = {0x34, 0x02},
703 .v_sync_line_aft_pxl_2 = {0x38, 0x07},
704 .v_sync_line_aft_pxl_1 = {0x38, 0x07},
705 .v_blank_f2 = {0xff, 0xff},
706 .v_blank_f3 = {0xff, 0xff},
707 .v_blank_f4 = {0xff, 0xff},
708 .v_blank_f5 = {0xff, 0xff},
709 .v_sync_line_aft_3 = {0xff, 0xff},
710 .v_sync_line_aft_4 = {0xff, 0xff},
711 .v_sync_line_aft_5 = {0xff, 0xff},
712 .v_sync_line_aft_6 = {0xff, 0xff},
713 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
714 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
715 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
716 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
717 .vact_space_1 = {0xff, 0xff},
718 .vact_space_2 = {0xff, 0xff},
719 .vact_space_3 = {0xff, 0xff},
720 .vact_space_4 = {0xff, 0xff},
721 .vact_space_5 = {0xff, 0xff},
722 .vact_space_6 = {0xff, 0xff},
723 /* other don't care */
724 }, 505 },
725 .tg = { 506 {
726 0x00, /* cmd */ 507 .pixel_clock = 40000000,
727 0x50, 0x0a, /* h_fsz */ 508 .conf = {
728 0xd0, 0x02, 0x80, 0x07, /* hact */ 509 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
729 0x65, 0x04, /* v_fsz */ 510 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
730 0x01, 0x00, 0x33, 0x02, /* vsync */ 511 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
731 0x16, 0x00, 0x1c, 0x02, /* vact */ 512 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
732 0x33, 0x02, /* field_chg */ 513 },
733 0x49, 0x02, /* vact_st2 */
734 0x00, 0x00, /* vact_st3 */
735 0x00, 0x00, /* vact_st4 */
736 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
737 0x01, 0x00, 0x33, 0x02, /* field top/bot */
738 0x00, /* 3d FP */
739 }, 514 },
740}; 515 {
741 516 .pixel_clock = 65000000,
742static const struct hdmi_preset_conf hdmi_conf_1080i60 = { 517 .conf = {
743 .core = { 518 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
744 .h_blank = {0x18, 0x01}, 519 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
745 .v2_blank = {0x32, 0x02}, 520 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
746 .v1_blank = {0x16, 0x00}, 521 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
747 .v_line = {0x65, 0x04}, 522 },
748 .h_line = {0x98, 0x08},
749 .hsync_pol = {0x00},
750 .vsync_pol = {0x00},
751 .int_pro_mode = {0x01},
752 .v_blank_f0 = {0x49, 0x02},
753 .v_blank_f1 = {0x65, 0x04},
754 .h_sync_start = {0x56, 0x00},
755 .h_sync_end = {0x82, 0x00},
756 .v_sync_line_bef_2 = {0x07, 0x00},
757 .v_sync_line_bef_1 = {0x02, 0x00},
758 .v_sync_line_aft_2 = {0x39, 0x02},
759 .v_sync_line_aft_1 = {0x34, 0x02},
760 .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
761 .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
762 .v_blank_f2 = {0xff, 0xff},
763 .v_blank_f3 = {0xff, 0xff},
764 .v_blank_f4 = {0xff, 0xff},
765 .v_blank_f5 = {0xff, 0xff},
766 .v_sync_line_aft_3 = {0xff, 0xff},
767 .v_sync_line_aft_4 = {0xff, 0xff},
768 .v_sync_line_aft_5 = {0xff, 0xff},
769 .v_sync_line_aft_6 = {0xff, 0xff},
770 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
771 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
772 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
773 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
774 .vact_space_1 = {0xff, 0xff},
775 .vact_space_2 = {0xff, 0xff},
776 .vact_space_3 = {0xff, 0xff},
777 .vact_space_4 = {0xff, 0xff},
778 .vact_space_5 = {0xff, 0xff},
779 .vact_space_6 = {0xff, 0xff},
780 /* other don't care */
781 }, 523 },
782 .tg = { 524 {
783 0x00, /* cmd */ 525 .pixel_clock = 74176000,
784 0x98, 0x08, /* h_fsz */ 526 .conf = {
785 0x18, 0x01, 0x80, 0x07, /* hact */ 527 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
786 0x65, 0x04, /* v_fsz */ 528 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
787 0x01, 0x00, 0x33, 0x02, /* vsync */ 529 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
788 0x16, 0x00, 0x1c, 0x02, /* vact */ 530 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
789 0x33, 0x02, /* field_chg */ 531 },
790 0x49, 0x02, /* vact_st2 */
791 0x00, 0x00, /* vact_st3 */
792 0x00, 0x00, /* vact_st4 */
793 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
794 0x01, 0x00, 0x33, 0x02, /* field top/bot */
795 0x00, /* 3d FP */
796 }, 532 },
797}; 533 {
798 534 .pixel_clock = 74250000,
799static const struct hdmi_preset_conf hdmi_conf_1080p30 = { 535 .conf = {
800 .core = { 536 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
801 .h_blank = {0x18, 0x01}, 537 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
802 .v2_blank = {0x65, 0x04}, 538 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
803 .v1_blank = {0x2d, 0x00}, 539 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
804 .v_line = {0x65, 0x04}, 540 },
805 .h_line = {0x98, 0x08},
806 .hsync_pol = {0x00},
807 .vsync_pol = {0x00},
808 .int_pro_mode = {0x00},
809 .v_blank_f0 = {0xff, 0xff},
810 .v_blank_f1 = {0xff, 0xff},
811 .h_sync_start = {0x56, 0x00},
812 .h_sync_end = {0x82, 0x00},
813 .v_sync_line_bef_2 = {0x09, 0x00},
814 .v_sync_line_bef_1 = {0x04, 0x00},
815 .v_sync_line_aft_2 = {0xff, 0xff},
816 .v_sync_line_aft_1 = {0xff, 0xff},
817 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
818 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
819 .v_blank_f2 = {0xff, 0xff},
820 .v_blank_f3 = {0xff, 0xff},
821 .v_blank_f4 = {0xff, 0xff},
822 .v_blank_f5 = {0xff, 0xff},
823 .v_sync_line_aft_3 = {0xff, 0xff},
824 .v_sync_line_aft_4 = {0xff, 0xff},
825 .v_sync_line_aft_5 = {0xff, 0xff},
826 .v_sync_line_aft_6 = {0xff, 0xff},
827 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
828 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
829 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
830 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
831 .vact_space_1 = {0xff, 0xff},
832 .vact_space_2 = {0xff, 0xff},
833 .vact_space_3 = {0xff, 0xff},
834 .vact_space_4 = {0xff, 0xff},
835 .vact_space_5 = {0xff, 0xff},
836 .vact_space_6 = {0xff, 0xff},
837 /* other don't care */
838 }, 541 },
839 .tg = { 542 {
840 0x00, /* cmd */ 543 .pixel_clock = 83500000,
841 0x98, 0x08, /* h_fsz */ 544 .conf = {
842 0x18, 0x01, 0x80, 0x07, /* hact */ 545 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
843 0x65, 0x04, /* v_fsz */ 546 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
844 0x01, 0x00, 0x33, 0x02, /* vsync */ 547 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
845 0x2d, 0x00, 0x38, 0x04, /* vact */ 548 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
846 0x33, 0x02, /* field_chg */ 549 },
847 0x48, 0x02, /* vact_st2 */
848 0x00, 0x00, /* vact_st3 */
849 0x00, 0x00, /* vact_st4 */
850 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
851 0x01, 0x00, 0x33, 0x02, /* field top/bot */
852 0x00, /* 3d FP */
853 }, 550 },
854}; 551 {
855 552 .pixel_clock = 106500000,
856static const struct hdmi_preset_conf hdmi_conf_1080p50 = { 553 .conf = {
857 .core = { 554 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
858 .h_blank = {0xd0, 0x02}, 555 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
859 .v2_blank = {0x65, 0x04}, 556 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
860 .v1_blank = {0x2d, 0x00}, 557 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
861 .v_line = {0x65, 0x04}, 558 },
862 .h_line = {0x50, 0x0a},
863 .hsync_pol = {0x00},
864 .vsync_pol = {0x00},
865 .int_pro_mode = {0x00},
866 .v_blank_f0 = {0xff, 0xff},
867 .v_blank_f1 = {0xff, 0xff},
868 .h_sync_start = {0x0e, 0x02},
869 .h_sync_end = {0x3a, 0x02},
870 .v_sync_line_bef_2 = {0x09, 0x00},
871 .v_sync_line_bef_1 = {0x04, 0x00},
872 .v_sync_line_aft_2 = {0xff, 0xff},
873 .v_sync_line_aft_1 = {0xff, 0xff},
874 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
875 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
876 .v_blank_f2 = {0xff, 0xff},
877 .v_blank_f3 = {0xff, 0xff},
878 .v_blank_f4 = {0xff, 0xff},
879 .v_blank_f5 = {0xff, 0xff},
880 .v_sync_line_aft_3 = {0xff, 0xff},
881 .v_sync_line_aft_4 = {0xff, 0xff},
882 .v_sync_line_aft_5 = {0xff, 0xff},
883 .v_sync_line_aft_6 = {0xff, 0xff},
884 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
885 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
886 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
887 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
888 .vact_space_1 = {0xff, 0xff},
889 .vact_space_2 = {0xff, 0xff},
890 .vact_space_3 = {0xff, 0xff},
891 .vact_space_4 = {0xff, 0xff},
892 .vact_space_5 = {0xff, 0xff},
893 .vact_space_6 = {0xff, 0xff},
894 /* other don't care */
895 }, 559 },
896 .tg = { 560 {
897 0x00, /* cmd */ 561 .pixel_clock = 108000000,
898 0x50, 0x0a, /* h_fsz */ 562 .conf = {
899 0xd0, 0x02, 0x80, 0x07, /* hact */ 563 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
900 0x65, 0x04, /* v_fsz */ 564 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
901 0x01, 0x00, 0x33, 0x02, /* vsync */ 565 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
902 0x2d, 0x00, 0x38, 0x04, /* vact */ 566 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
903 0x33, 0x02, /* field_chg */ 567 },
904 0x48, 0x02, /* vact_st2 */
905 0x00, 0x00, /* vact_st3 */
906 0x00, 0x00, /* vact_st4 */
907 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
908 0x01, 0x00, 0x33, 0x02, /* field top/bot */
909 0x00, /* 3d FP */
910 }, 568 },
911}; 569 {
912 570 .pixel_clock = 146250000,
913static const struct hdmi_preset_conf hdmi_conf_1080p60 = { 571 .conf = {
914 .core = { 572 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
915 .h_blank = {0x18, 0x01}, 573 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
916 .v2_blank = {0x65, 0x04}, 574 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
917 .v1_blank = {0x2d, 0x00}, 575 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
918 .v_line = {0x65, 0x04}, 576 },
919 .h_line = {0x98, 0x08},
920 .hsync_pol = {0x00},
921 .vsync_pol = {0x00},
922 .int_pro_mode = {0x00},
923 .v_blank_f0 = {0xff, 0xff},
924 .v_blank_f1 = {0xff, 0xff},
925 .h_sync_start = {0x56, 0x00},
926 .h_sync_end = {0x82, 0x00},
927 .v_sync_line_bef_2 = {0x09, 0x00},
928 .v_sync_line_bef_1 = {0x04, 0x00},
929 .v_sync_line_aft_2 = {0xff, 0xff},
930 .v_sync_line_aft_1 = {0xff, 0xff},
931 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
932 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
933 .v_blank_f2 = {0xff, 0xff},
934 .v_blank_f3 = {0xff, 0xff},
935 .v_blank_f4 = {0xff, 0xff},
936 .v_blank_f5 = {0xff, 0xff},
937 .v_sync_line_aft_3 = {0xff, 0xff},
938 .v_sync_line_aft_4 = {0xff, 0xff},
939 .v_sync_line_aft_5 = {0xff, 0xff},
940 .v_sync_line_aft_6 = {0xff, 0xff},
941 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
942 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
943 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
944 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
945 /* other don't care */
946 }, 577 },
947 .tg = { 578 {
948 0x00, /* cmd */ 579 .pixel_clock = 148500000,
949 0x98, 0x08, /* h_fsz */ 580 .conf = {
950 0x18, 0x01, 0x80, 0x07, /* hact */ 581 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
951 0x65, 0x04, /* v_fsz */ 582 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
952 0x01, 0x00, 0x33, 0x02, /* vsync */ 583 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
953 0x2d, 0x00, 0x38, 0x04, /* vact */ 584 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
954 0x33, 0x02, /* field_chg */ 585 },
955 0x48, 0x02, /* vact_st2 */
956 0x00, 0x00, /* vact_st3 */
957 0x00, 0x00, /* vact_st4 */
958 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
959 0x01, 0x00, 0x33, 0x02, /* field top/bot */
960 0x00, /* 3d FP */
961 }, 586 },
962}; 587};
963 588
964static const struct hdmi_conf hdmi_confs[] = {
965 { 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 },
966 { 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 },
967 { 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 },
968 { 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
969 { 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
970 { 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
971 { 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
972 { 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
973};
974
975struct hdmi_infoframe { 589struct hdmi_infoframe {
976 enum HDMI_PACKET_TYPE type; 590 enum HDMI_PACKET_TYPE type;
977 u8 ver; 591 u8 ver;
@@ -1275,31 +889,6 @@ static int hdmi_v13_conf_index(struct drm_display_mode *mode)
1275 return -EINVAL; 889 return -EINVAL;
1276} 890}
1277 891
1278static int hdmi_v14_conf_index(struct drm_display_mode *mode)
1279{
1280 int i;
1281
1282 for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i)
1283 if (hdmi_confs[i].width == mode->hdisplay &&
1284 hdmi_confs[i].height == mode->vdisplay &&
1285 hdmi_confs[i].vrefresh == mode->vrefresh &&
1286 hdmi_confs[i].interlace ==
1287 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1288 true : false))
1289 return i;
1290
1291 return -EINVAL;
1292}
1293
1294static int hdmi_conf_index(struct hdmi_context *hdata,
1295 struct drm_display_mode *mode)
1296{
1297 if (hdata->type == HDMI_TYPE13)
1298 return hdmi_v13_conf_index(mode);
1299
1300 return hdmi_v14_conf_index(mode);
1301}
1302
1303static u8 hdmi_chksum(struct hdmi_context *hdata, 892static u8 hdmi_chksum(struct hdmi_context *hdata,
1304 u32 start, u8 len, u32 hdr_sum) 893 u32 start, u8 len, u32 hdr_sum)
1305{ 894{
@@ -1357,7 +946,7 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
1357 if (hdata->type == HDMI_TYPE13) 946 if (hdata->type == HDMI_TYPE13)
1358 vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id; 947 vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id;
1359 else 948 else
1360 vic = hdmi_confs[hdata->cur_conf].cea_video_id; 949 vic = hdata->mode_conf.cea_video_id;
1361 950
1362 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); 951 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
1363 952
@@ -1434,44 +1023,51 @@ static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
1434 return -EINVAL; 1023 return -EINVAL;
1435} 1024}
1436 1025
1026static int hdmi_v14_find_phy_conf(int pixel_clock)
1027{
1028 int i;
1029
1030 for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++) {
1031 if (hdmiphy_v14_configs[i].pixel_clock == pixel_clock)
1032 return i;
1033 }
1034
1035 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
1036 return -EINVAL;
1037}
1038
1437static int hdmi_v14_check_timing(struct fb_videomode *check_timing) 1039static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1438{ 1040{
1439 int i; 1041 int i;
1440 1042
1441 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", 1043 DRM_DEBUG_KMS("mode: xres=%d, yres=%d, refresh=%d, clock=%d, intl=%d\n",
1442 check_timing->xres, check_timing->yres, 1044 check_timing->xres, check_timing->yres,
1443 check_timing->refresh, (check_timing->vmode & 1045 check_timing->refresh, check_timing->pixclock,
1444 FB_VMODE_INTERLACED) ? true : false); 1046 (check_timing->vmode & FB_VMODE_INTERLACED) ?
1047 true : false);
1445 1048
1446 for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++) 1049 for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++)
1447 if (hdmi_confs[i].width == check_timing->xres && 1050 if (hdmiphy_v14_configs[i].pixel_clock ==
1448 hdmi_confs[i].height == check_timing->yres && 1051 check_timing->pixclock)
1449 hdmi_confs[i].vrefresh == check_timing->refresh && 1052 return 0;
1450 hdmi_confs[i].interlace ==
1451 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1452 true : false))
1453 return 0;
1454
1455 /* TODO */
1456 1053
1457 return -EINVAL; 1054 return -EINVAL;
1458} 1055}
1459 1056
1460static int hdmi_check_timing(void *ctx, void *timing) 1057static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
1461{ 1058{
1462 struct hdmi_context *hdata = ctx; 1059 struct hdmi_context *hdata = ctx;
1463 struct fb_videomode *check_timing = timing;
1464 1060
1465 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 1061 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1466 1062
1467 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres, 1063 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres,
1468 check_timing->yres, check_timing->refresh, 1064 timing->yres, timing->refresh,
1469 check_timing->vmode); 1065 timing->vmode);
1470 1066
1471 if (hdata->type == HDMI_TYPE13) 1067 if (hdata->type == HDMI_TYPE13)
1472 return hdmi_v13_check_timing(check_timing); 1068 return hdmi_v13_check_timing(timing);
1473 else 1069 else
1474 return hdmi_v14_check_timing(check_timing); 1070 return hdmi_v14_check_timing(timing);
1475} 1071}
1476 1072
1477static void hdmi_set_acr(u32 freq, u8 *acr) 1073static void hdmi_set_acr(u32 freq, u8 *acr)
@@ -1795,9 +1391,8 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
1795 1391
1796static void hdmi_v14_timing_apply(struct hdmi_context *hdata) 1392static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1797{ 1393{
1798 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf; 1394 struct hdmi_core_regs *core = &hdata->mode_conf.core;
1799 const struct hdmi_core_regs *core = &conf->core; 1395 struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
1800 const struct hdmi_tg_regs *tg = &conf->tg;
1801 int tries; 1396 int tries;
1802 1397
1803 /* setting core registers */ 1398 /* setting core registers */
@@ -1900,39 +1495,39 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1900 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]); 1495 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1901 1496
1902 /* Timing generator registers */ 1497 /* Timing generator registers */
1903 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); 1498 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1904 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); 1499 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1905 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); 1500 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1906 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); 1501 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1907 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); 1502 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1908 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); 1503 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1909 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); 1504 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1910 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); 1505 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1911 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); 1506 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1912 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); 1507 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1913 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); 1508 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1914 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); 1509 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1915 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); 1510 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1916 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); 1511 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1917 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); 1512 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1918 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); 1513 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1919 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); 1514 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1920 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); 1515 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1921 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); 1516 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1922 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); 1517 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1923 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l); 1518 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
1924 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h); 1519 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
1925 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l); 1520 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
1926 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h); 1521 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
1927 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); 1522 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1928 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); 1523 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1929 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); 1524 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1930 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); 1525 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1931 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); 1526 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1932 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); 1527 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1933 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); 1528 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1934 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); 1529 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1935 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d); 1530 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
1936 1531
1937 /* waiting for HDMIPHY's PLL to get to steady state */ 1532 /* waiting for HDMIPHY's PLL to get to steady state */
1938 for (tries = 100; tries; --tries) { 1533 for (tries = 100; tries; --tries) {
@@ -2029,10 +1624,17 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
2029 } 1624 }
2030 1625
2031 /* pixel clock */ 1626 /* pixel clock */
2032 if (hdata->type == HDMI_TYPE13) 1627 if (hdata->type == HDMI_TYPE13) {
2033 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data; 1628 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
2034 else 1629 } else {
2035 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data; 1630 i = hdmi_v14_find_phy_conf(hdata->mode_conf.pixel_clock);
1631 if (i < 0) {
1632 DRM_ERROR("failed to find hdmiphy conf\n");
1633 return;
1634 }
1635
1636 hdmiphy_data = hdmiphy_v14_configs[i].conf;
1637 }
2036 1638
2037 memcpy(buffer, hdmiphy_data, 32); 1639 memcpy(buffer, hdmiphy_data, 32);
2038 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32); 1640 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
@@ -2100,7 +1702,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
2100 if (hdata->type == HDMI_TYPE13) 1702 if (hdata->type == HDMI_TYPE13)
2101 index = hdmi_v13_conf_index(adjusted_mode); 1703 index = hdmi_v13_conf_index(adjusted_mode);
2102 else 1704 else
2103 index = hdmi_v14_conf_index(adjusted_mode); 1705 index = hdmi_v14_find_phy_conf(adjusted_mode->clock * 1000);
2104 1706
2105 /* just return if user desired mode exists. */ 1707 /* just return if user desired mode exists. */
2106 if (index >= 0) 1708 if (index >= 0)
@@ -2114,7 +1716,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
2114 if (hdata->type == HDMI_TYPE13) 1716 if (hdata->type == HDMI_TYPE13)
2115 index = hdmi_v13_conf_index(m); 1717 index = hdmi_v13_conf_index(m);
2116 else 1718 else
2117 index = hdmi_v14_conf_index(m); 1719 index = hdmi_v14_find_phy_conf(m->clock * 1000);
2118 1720
2119 if (index >= 0) { 1721 if (index >= 0) {
2120 struct drm_mode_object base; 1722 struct drm_mode_object base;
@@ -2123,6 +1725,9 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
2123 DRM_INFO("desired mode doesn't exist so\n"); 1725 DRM_INFO("desired mode doesn't exist so\n");
2124 DRM_INFO("use the most suitable mode among modes.\n"); 1726 DRM_INFO("use the most suitable mode among modes.\n");
2125 1727
1728 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
1729 m->hdisplay, m->vdisplay, m->vrefresh);
1730
2126 /* preserve display mode header while copying. */ 1731 /* preserve display mode header while copying. */
2127 head = adjusted_mode->head; 1732 head = adjusted_mode->head;
2128 base = adjusted_mode->base; 1733 base = adjusted_mode->base;
@@ -2134,6 +1739,122 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
2134 } 1739 }
2135} 1740}
2136 1741
1742static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1743{
1744 int i;
1745 BUG_ON(num_bytes > 4);
1746 for (i = 0; i < num_bytes; i++)
1747 reg_pair[i] = (value >> (8 * i)) & 0xff;
1748}
1749
1750static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1751 struct drm_display_mode *m)
1752{
1753 struct hdmi_core_regs *core = &hdata->mode_conf.core;
1754 struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
1755
1756 hdata->mode_conf.cea_video_id = drm_match_cea_mode(m);
1757
1758 hdata->mode_conf.pixel_clock = m->clock * 1000;
1759 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1760 hdmi_set_reg(core->v_line, 2, m->vtotal);
1761 hdmi_set_reg(core->h_line, 2, m->htotal);
1762 hdmi_set_reg(core->hsync_pol, 1,
1763 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1764 hdmi_set_reg(core->vsync_pol, 1,
1765 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1766 hdmi_set_reg(core->int_pro_mode, 1,
1767 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1768
1769 /*
1770 * Quirk requirement for exynos 5 HDMI IP design,
1771 * 2 pixels less than the actual calculation for hsync_start
1772 * and end.
1773 */
1774
1775 /* Following values & calculations differ for different type of modes */
1776 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1777 /* Interlaced Mode */
1778 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1779 (m->vsync_end - m->vdisplay) / 2);
1780 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1781 (m->vsync_start - m->vdisplay) / 2);
1782 hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
1783 hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
1784 hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal +
1785 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2);
1786 hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
1787 hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
1788 hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
1789 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
1790 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1791 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
1792 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1793 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1794 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1795 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1796 hdmi_set_reg(tg->vact_st3, 2, 0x0);
1797 hdmi_set_reg(tg->vact_st4, 2, 0x0);
1798 } else {
1799 /* Progressive Mode */
1800 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1801 m->vsync_end - m->vdisplay);
1802 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1803 m->vsync_start - m->vdisplay);
1804 hdmi_set_reg(core->v2_blank, 2, m->vtotal);
1805 hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
1806 hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
1807 hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
1808 hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
1809 hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
1810 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
1811 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
1812 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1813 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1814 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1815 hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
1816 hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
1817 }
1818
1819 /* Following values & calculations are same irrespective of mode type */
1820 hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
1821 hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
1822 hdmi_set_reg(core->vact_space_1, 2, 0xffff);
1823 hdmi_set_reg(core->vact_space_2, 2, 0xffff);
1824 hdmi_set_reg(core->vact_space_3, 2, 0xffff);
1825 hdmi_set_reg(core->vact_space_4, 2, 0xffff);
1826 hdmi_set_reg(core->vact_space_5, 2, 0xffff);
1827 hdmi_set_reg(core->vact_space_6, 2, 0xffff);
1828 hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
1829 hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
1830 hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
1831 hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
1832 hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
1833 hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
1834 hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
1835 hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
1836 hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
1837 hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
1838 hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
1839 hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
1840
1841 /* Timing generator registers */
1842 hdmi_set_reg(tg->cmd, 1, 0x0);
1843 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1844 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1845 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1846 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1847 hdmi_set_reg(tg->vsync, 2, 0x1);
1848 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1849 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1850 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1851 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1852 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1853 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1854 hdmi_set_reg(tg->tg_3d, 1, 0x0);
1855
1856}
1857
2137static void hdmi_mode_set(void *ctx, void *mode) 1858static void hdmi_mode_set(void *ctx, void *mode)
2138{ 1859{
2139 struct hdmi_context *hdata = ctx; 1860 struct hdmi_context *hdata = ctx;
@@ -2141,11 +1862,15 @@ static void hdmi_mode_set(void *ctx, void *mode)
2141 1862
2142 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 1863 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2143 1864
2144 conf_idx = hdmi_conf_index(hdata, mode); 1865 if (hdata->type == HDMI_TYPE13) {
2145 if (conf_idx >= 0) 1866 conf_idx = hdmi_v13_conf_index(mode);
2146 hdata->cur_conf = conf_idx; 1867 if (conf_idx >= 0)
2147 else 1868 hdata->cur_conf = conf_idx;
2148 DRM_DEBUG_KMS("not supported mode\n"); 1869 else
1870 DRM_DEBUG_KMS("not supported mode\n");
1871 } else {
1872 hdmi_v14_mode_set(hdata, mode);
1873 }
2149} 1874}
2150 1875
2151static void hdmi_get_max_resol(void *ctx, unsigned int *width, 1876static void hdmi_get_max_resol(void *ctx, unsigned int *width,
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index c414584bfbae..e919aba29b3d 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -284,13 +284,13 @@ static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
284 MXR_CFG_SCAN_PROGRASSIVE); 284 MXR_CFG_SCAN_PROGRASSIVE);
285 285
286 /* choosing between porper HD and SD mode */ 286 /* choosing between porper HD and SD mode */
287 if (height == 480) 287 if (height <= 480)
288 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD; 288 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
289 else if (height == 576) 289 else if (height <= 576)
290 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD; 290 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
291 else if (height == 720) 291 else if (height <= 720)
292 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; 292 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
293 else if (height == 1080) 293 else if (height <= 1080)
294 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD; 294 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
295 else 295 else
296 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; 296 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
@@ -818,6 +818,29 @@ static void mixer_win_disable(void *ctx, int win)
818 mixer_ctx->win_data[win].enabled = false; 818 mixer_ctx->win_data[win].enabled = false;
819} 819}
820 820
821int mixer_check_timing(void *ctx, struct fb_videomode *timing)
822{
823 struct mixer_context *mixer_ctx = ctx;
824 u32 w, h;
825
826 w = timing->xres;
827 h = timing->yres;
828
829 DRM_DEBUG_KMS("%s : xres=%d, yres=%d, refresh=%d, intl=%d\n",
830 __func__, timing->xres, timing->yres,
831 timing->refresh, (timing->vmode &
832 FB_VMODE_INTERLACED) ? true : false);
833
834 if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16)
835 return 0;
836
837 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
838 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
839 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
840 return 0;
841
842 return -EINVAL;
843}
821static void mixer_wait_for_vblank(void *ctx) 844static void mixer_wait_for_vblank(void *ctx)
822{ 845{
823 struct mixer_context *mixer_ctx = ctx; 846 struct mixer_context *mixer_ctx = ctx;
@@ -955,6 +978,9 @@ static struct exynos_mixer_ops mixer_ops = {
955 .win_mode_set = mixer_win_mode_set, 978 .win_mode_set = mixer_win_mode_set,
956 .win_commit = mixer_win_commit, 979 .win_commit = mixer_win_commit,
957 .win_disable = mixer_win_disable, 980 .win_disable = mixer_win_disable,
981
982 /* display */
983 .check_timing = mixer_check_timing,
958}; 984};
959 985
960static irqreturn_t mixer_irq_handler(int irq, void *arg) 986static irqreturn_t mixer_irq_handler(int irq, void *arg)