diff --git a/projects/imx6/patches/linux/3.14-mx6-sr/linux-800-from-openbricks.patch b/projects/imx6/patches/linux/3.14-mx6-sr/linux-800-from-openbricks.patch new file mode 100644 index 0000000000..58d8fea88e --- /dev/null +++ b/projects/imx6/patches/linux/3.14-mx6-sr/linux-800-from-openbricks.patch @@ -0,0 +1,1880 @@ +https://github.com/OpenBricks/openbricks/tree/krypton-glibc +https://github.com/OpenBricks/openbricks/tree/krypton-glibc/config/platforms/arm/imx6/machines/cuboxi/packages/linux/patches +https://github.com/OpenBricks/openbricks/tree/32da31689ba04a94d1a08bfc04f69d6c1a3c848a/config/platforms/arm/imx6/machines/cuboxi/packages/linux/patches + +============================================================== +file 0004-Dumb_adapter.patch +============================================================== + +commit c466ada304c10af850daaef8b232e0e818bfb6d7 +Author: wolfgar +Date: Sat Sep 13 02:08:32 2014 +0200 + + Remove embedded logics from the driver so that libcec is responsible for + all this work + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index c30237e..fb66c25 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -123,7 +123,7 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + + void mxc_hdmi_cec_handle(u16 cec_stat) + { +- u8 val = 0, i = 0; ++ u8 i = 0; + struct hdmi_cec_event *event = NULL; + /*The current transmission is successful (for initiator only).*/ + if (!open_count) +@@ -158,27 +158,14 @@ void mxc_hdmi_cec_handle(u16 cec_stat) + } + /*An error is detected on cec line (for initiator only). */ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) { +- mutex_lock(&hdmi_cec_data.lock); +- hdmi_cec_data.send_error++; +- if (hdmi_cec_data.send_error > 2) { +- pr_err("%s:Re-transmission is attempted more than 2 times!\n", __func__); +- hdmi_cec_data.send_error = 0; +- mutex_unlock(&hdmi_cec_data.lock); +- hdmi_cec_data.tx_answer = cec_stat; +- wake_up(&tx_cec_queue); +- return; +- } +- for (i = 0; i < hdmi_cec_data.msg_len; i++) +- hdmi_writeb(hdmi_cec_data.last_msg[i], HDMI_CEC_TX_DATA0+i); +- hdmi_writeb(hdmi_cec_data.msg_len, HDMI_CEC_TX_CNT); +- val = hdmi_readb(HDMI_CEC_CTRL); +- val |= 0x01; +- hdmi_writeb(val, HDMI_CEC_CTRL); +- mutex_unlock(&hdmi_cec_data.lock); ++ hdmi_cec_data.tx_answer = cec_stat; ++ wake_up(&tx_cec_queue); ++ return; + } + /*A frame is not acknowledged in a directly addressed message. Or a frame is negatively acknowledged in + a broadcast message (for initiator only).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_NACK) { ++ hdmi_cec_data.send_error++; + hdmi_cec_data.tx_answer = cec_stat; + wake_up(&tx_cec_queue); + } +@@ -392,7 +379,7 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + u_long arg) + { + int ret = 0, status = 0; +- u8 val = 0, msg = 0; ++ u8 val = 0; + struct mxc_edid_cfg hdmi_edid_cfg; + pr_debug("function : %s\n", __func__); + if (!open_count) +@@ -416,15 +403,6 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + hdmi_writeb(0, HDMI_CEC_ADDR_L); + } else + ret = -EINVAL; +- /*Send Polling message with same source and destination address*/ +- if (0 == ret && 15 != hdmi_cec_data.Logical_address) { +- msg = (hdmi_cec_data.Logical_address << 4)|hdmi_cec_data.Logical_address; +- hdmi_writeb(1, HDMI_CEC_TX_CNT); +- hdmi_writeb(msg, HDMI_CEC_TX_DATA0); +- val = hdmi_readb(HDMI_CEC_CTRL); +- val |= 0x01; +- hdmi_writeb(val, HDMI_CEC_CTRL); +- } + mutex_unlock(&hdmi_cec_data.lock); + break; + case HDMICEC_IOC_STARTDEVICE: + +============================================================== +file 0005-assign-minor-to-vhci.patch +============================================================== + +From 27b8b64082db6cdfda751e81e56c0f668053834b Mon Sep 17 00:00:00 2001 +From: Lucas De Marchi +Date: Tue, 18 Feb 2014 02:19:26 -0300 +Subject: [PATCH] Bluetooth: allocate static minor for vhci + +Commit bfacbb9 (Bluetooth: Use devname:vhci module alias for virtual HCI +driver) added the module alias to hci_vhci module so it's possible to +create the /dev/vhci node. However creating an alias without +specifying the minor doesn't allow us to create the node ahead, +triggerring module auto-load when it's first accessed. + +Starting with depmod from kmod 16 we started to warn if there's a +devname alias without specifying the major and minor. + +Let's do the same done for uhid, kvm, fuse and others, specifying a +fixed minor. In systems with systemd as the init the following will +happen: on early boot systemd will call "kmod static-nodes" to read +/lib/modules/$(uname -r)/modules.devname and then create the nodes. When +first accessed these "dead" nodes will trigger the module loading. + +Signed-off-by: Lucas De Marchi +Acked-by: Greg Kroah-Hartman +Signed-off-by: Marcel Holtmann +--- + Documentation/devices.txt | 1 + + drivers/bluetooth/hci_vhci.c | 3 ++- + include/linux/miscdevice.h | 1 + + 3 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devices.txt b/Documentation/devices.txt +index 10378cc..04356f5 100644 +--- a/Documentation/devices.txt ++++ b/Documentation/devices.txt +@@ -353,6 +353,7 @@ Your cooperation is appreciated. + 133 = /dev/exttrp External device trap + 134 = /dev/apm_bios Advanced Power Management BIOS + 135 = /dev/rtc Real Time Clock ++ 137 = /dev/vhci Bluetooth virtual HCI driver + 139 = /dev/openprom SPARC OpenBoot PROM + 140 = /dev/relay8 Berkshire Products Octal relay card + 141 = /dev/relay16 Berkshire Products ISO-16 relay card +diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c +index 1ef6990..add1c6a 100644 +--- a/drivers/bluetooth/hci_vhci.c ++++ b/drivers/bluetooth/hci_vhci.c +@@ -359,7 +359,7 @@ static const struct file_operations vhci_fops = { + static struct miscdevice vhci_miscdev= { + .name = "vhci", + .fops = &vhci_fops, +- .minor = MISC_DYNAMIC_MINOR, ++ .minor = VHCI_MINOR, + }; + + static int __init vhci_init(void) +@@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); + MODULE_VERSION(VERSION); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("devname:vhci"); ++MODULE_ALIAS_MISCDEV(VHCI_MINOR); +diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h +index 3737f72..7bb6148 100644 +--- a/include/linux/miscdevice.h ++++ b/include/linux/miscdevice.h +@@ -23,6 +23,7 @@ + #define TEMP_MINOR 131 /* Temperature Sensor */ + #define RTC_MINOR 135 + #define EFI_RTC_MINOR 136 /* EFI Time services */ ++#define VHCI_MINOR 137 + #define SUN_OPENPROM_MINOR 139 + #define DMAPI_MINOR 140 /* DMAPI */ + #define NVRAM_MINOR 144 + +============================================================== +file 1100-ARM-Avoid-crash-on-power-off-and-reduce-power-consum.patch +============================================================== + +From 7a4bc357a0d2477c0dcdf2a1c471e57050dec041 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 20 Sep 2014 14:05:50 +0200 +Subject: [PATCH] ARM: Avoid crash on power off and reduce power consumption + in 'halt' state. + +Signed-off-by: Rudi +--- + arch/arm/kernel/process.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 1bdd78b..70655b9 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -119,6 +119,17 @@ static void null_restart(enum reboot_mode reboot_mode, const char *cmd) + } + + /* ++ * Enter non-interruptable CPU halt state ++ */ ++static void cpu_halt(void) ++{ ++ local_irq_disable(); ++ ++ while (1) ++ cpu_do_idle(); ++} ++ ++/* + * Function pointers to optional machine specific functions + */ + void (*pm_power_off)(void); +@@ -202,8 +213,7 @@ void machine_halt(void) + local_irq_disable(); + smp_send_stop(); + +- local_irq_disable(); +- while (1); ++ cpu_halt(); + } + + /* +@@ -219,6 +229,8 @@ void machine_power_off(void) + + if (pm_power_off) + pm_power_off(); ++ ++ cpu_halt(); + } + + /* +@@ -244,8 +256,7 @@ void machine_restart(char *cmd) + + /* Whoops - the platform was unable to reboot. Tell the user! */ + printk("Reboot failed -- System halted\n"); +- local_irq_disable(); +- while (1); ++ cpu_halt(); + } + + void __show_regs(struct pt_regs *regs) +-- +1.7.9.5 + + +============================================================== +file 1101-ARM-Disable-timer-events-before-entering-halt-state.patch +============================================================== + +From ae0f301a11bb9d5e484d48238cf15082928a7241 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sun, 21 Sep 2014 13:53:21 +0200 +Subject: [PATCH] ARM: Disable timer events before entering `halt' state. + +Signed-off-by: Rudi +--- + arch/arm/kernel/process.c | 3 ++- + arch/arm/mach-imx/time.c | 11 +++++++++++ + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 70655b9..d1e4763 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -123,8 +123,9 @@ static void null_restart(enum reboot_mode reboot_mode, const char *cmd) + */ + static void cpu_halt(void) + { ++ clockevents_suspend(); ++ + local_irq_disable(); +- + while (1) + cpu_do_idle(); + } +diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c +index ae61dfd..75afcf9 100644 +--- a/arch/arm/mach-imx/time.c ++++ b/arch/arm/mach-imx/time.c +@@ -232,6 +232,16 @@ static void mxc_set_mode(enum clock_event_mode mode, + } + } + ++ ++/* ++ * Shutdown timer ++ */ ++static void mxc_suspend(struct clock_event_device *evt) ++{ ++ mxc_set_mode(CLOCK_EVT_MODE_SHUTDOWN, evt); ++} ++ ++ + /* + * IRQ handler for the timer + */ +@@ -262,6 +272,7 @@ static struct clock_event_device clockevent_mxc = { + .name = "mxc_timer1", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = mxc_set_mode, ++ .suspend = mxc_suspend, + .set_next_event = mx1_2_set_next_event, + .rating = 200, + }; +-- +1.7.9.5 + + +============================================================== +file 1104-interlaced-fix.patch +============================================================== + +From d6c338100ddd885a7acb1d0cf12da90fa7ac2b93 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Wed, 30 Dec 2015 11:01:32 +0100 +Subject: [PATCH] video: ipu_disp: Fix internal VSYNC clock for interlaced + modes + +Signed-off-by: Rudi +--- + drivers/mxc/ipu3/ipu_disp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c +index b5e21c5..96464b2 100644 +--- a/drivers/mxc/ipu3/ipu_disp.c ++++ b/drivers/mxc/ipu3/ipu_disp.c +@@ -1189,7 +1189,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk, + _ipu_di_sync_config(ipu, + disp, /* display */ + DI_SYNC_COUNT_1, /* counter */ +- v_total*2 - 1, /* run count */ ++ v_total - 1, /* run count */ + (3 - 1), /* run_resolution, counter 1 can reference to counter 6,7,8 with run_resolution=2,3,4 */ + 1, /* offset */ + (3 - 1), /* offset resolution, 3=counter 7 */ +-- +1.9.1 + + +============================================================== +file 1110-video-mxc_hdmi-Use-common-function-to-insert-video-m.patch +============================================================== + +From a86bd823319cf21eec118f238e2d3e97ede3690f Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 08:13:24 +0100 +Subject: [PATCH] video: mxc_hdmi: Use common function to insert video modes + +To simplify further development we move the mode list entry +creation into a single function. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_hdmi.c | 145 ++++++++++++++++++------------------------- + 1 file changed, 60 insertions(+), 85 deletions(-) + +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index 55c39e1..f71c1dd 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -1740,7 +1740,8 @@ static int mxc_edid_read_internal(struct mxc_hdmi *hdmi, unsigned char *edid, + + static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi) + { +- int ret; ++ int ret, n; ++ struct fb_videomode *mode; + u8 edid_old[HDMI_EDID_LEN]; + u8 clkdis; + +@@ -1774,19 +1775,36 @@ static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi) + + } + +- if (ret < 0) ++ if (ret < 0) { ++ dev_err(&hdmi->pdev->dev, "Failed to read EDID\n"); + return HDMI_EDID_FAIL; ++ } + + if (memcmp(edid_old, hdmi->edid, HDMI_EDID_LEN) == 0) { +- dev_info(&hdmi->pdev->dev, "same edid\n"); ++ dev_info(&hdmi->pdev->dev, "Same EDID\n"); + return HDMI_EDID_SAME; + } + + if (hdmi->fbi->monspecs.modedb_len == 0) { +- dev_info(&hdmi->pdev->dev, "No modes read from edid\n"); ++ dev_warn(&hdmi->pdev->dev, "No modes read from EDID\n"); + return HDMI_EDID_NO_MODES; + } + ++ /* TODO: Is this really neccessary? */ ++ mode = hdmi->fbi->monspecs.modedb; ++ n = hdmi->fbi->monspecs.modedb_len; ++ while (n--) { ++ if ((mode->flag & FB_MODE_IS_STANDARD) && ++ !(mode->vmode & FB_VMODE_ASPECT_MASK)) { ++ if (mode->yres == (mode->xres * 3)/4) ++ mode->vmode |= FB_VMODE_ASPECT_4_3; ++ else ++ mode->vmode |= FB_VMODE_ASPECT_16_9; ++ } ++ ++ mode++; ++ } ++ + return HDMI_EDID_SUCCESS; + } + +@@ -1928,51 +1946,53 @@ static void mxc_hdmi_notify_fb(struct mxc_hdmi *hdmi, bool force_all) + dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__); + } + +-static void mxc_hdmi_edid_rebuild_modelist(struct mxc_hdmi *hdmi) ++static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + { +- int i, vic; +- struct fb_videomode *mode; ++ struct fb_videomode mode; ++ int i, vic, mode_count = ARRAY_SIZE(mxc_cea_mode); ++ const struct fb_videomode *mode_data = mxc_cea_mode; ++ ++ if (from_edid) { ++ mode_data = hdmi->fbi->monspecs.modedb; ++ mode_count = hdmi->fbi->monspecs.modedb_len; ++ } + + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); + + console_lock(); + + fb_destroy_modelist(&hdmi->fbi->modelist); ++ ++ /* Always insert VGA mode */ + fb_add_videomode(&vga_mode, &hdmi->fbi->modelist); + +- for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) { +- /* +- * We might check here if mode is supported by HDMI. +- * We do not currently support interlaced modes. +- * And add CEA modes in the modelist. +- */ +- mode = &hdmi->fbi->monspecs.modedb[i]; +- +- vic = mxc_edid_mode_to_vic(mode); +- if (hdmi->edid_cfg.hdmi_cap && +- (vic == 0)) ++ for (i = 0; i < mode_count; i++) { ++ vic = from_edid ? mxc_edid_mode_to_vic(&mode_data[i]) : i; ++ ++ if (mode_data[i].xres == 0 || ++ (hdmi->edid_cfg.hdmi_cap && vic == 0)) + continue; + +- if (!(mode->vmode & FB_VMODE_ASPECT_MASK)) { +- if (mode->yres == (mode->xres * 3)/4) +- mode->vmode |= FB_VMODE_ASPECT_4_3; +- else +- mode->vmode |= FB_VMODE_ASPECT_16_9; +- } ++ mode = mode_data[i]; ++ ++ /* TODO: Discuss if we should always set default modes as standard */ ++ if (!from_edid /*&& ignore_edid*/) ++ mode.flag |= FB_MODE_IS_STANDARD; + +- if (fb_add_videomode(mode, &hdmi->fbi->modelist)) ++ if (fb_add_videomode(&mode, &hdmi->fbi->modelist)) + continue; + + dev_dbg(&hdmi->pdev->dev, "Added mode: %d, vic: %d", i, vic); + dev_dbg(&hdmi->pdev->dev, +- "xres = %d, yres = %d, ratio = %s, freq = %d, vmode = %d, flag = %d\n", +- hdmi->fbi->monspecs.modedb[i].xres, +- hdmi->fbi->monspecs.modedb[i].yres, +- mode->vmode & FB_VMODE_ASPECT_4_3 ? "4/3" : +- mode->vmode & FB_VMODE_ASPECT_16_9 ? "16/9" : "n/a", +- hdmi->fbi->monspecs.modedb[i].refresh, +- hdmi->fbi->monspecs.modedb[i].vmode, +- hdmi->fbi->monspecs.modedb[i].flag); ++ "xres = %d, yres = %d, scan = %c, ratio = %s, freq = %d, vmode = %d, flag = %d\n", ++ mode.xres, ++ mode.yres, ++ mode.vmode & FB_VMODE_INTERLACED ? 'i' : 'p', ++ mode.vmode & FB_VMODE_ASPECT_4_3 ? "4/3" : ++ mode.vmode & FB_VMODE_ASPECT_16_9 ? "16/9" : "n/a", ++ mode.refresh, ++ mode.vmode, ++ mode.flag); + } + + fb_new_modelist(hdmi->fbi); +@@ -1986,36 +2006,6 @@ static void mxc_hdmi_default_edid_cfg(struct mxc_hdmi *hdmi) + hdmi->edid_cfg.hdmi_cap = true; + } + +-static void mxc_hdmi_default_modelist(struct mxc_hdmi *hdmi) +-{ +- u32 i; +- struct fb_videomode mode; +- +- dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); +- +- /* If not EDID data read, set up default modelist */ +- dev_info(&hdmi->pdev->dev, "No modes read from edid\n"); +- dev_info(&hdmi->pdev->dev, "create default modelist\n"); +- +- console_lock(); +- +- fb_destroy_modelist(&hdmi->fbi->modelist); +- +- /*Add all no interlaced CEA mode to default modelist */ +- for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) { +- mode = mxc_cea_mode[i]; +- if (mode.xres != 0) { +- if (ignore_edid) +- mode.flag |= FB_MODE_IS_STANDARD; +- fb_add_videomode(&mode, &hdmi->fbi->modelist); +- } +- } +- +- fb_new_modelist(hdmi->fbi); +- +- console_unlock(); +-} +- + static void mxc_hdmi_set_mode(struct mxc_hdmi *hdmi, int edid_status) + { + const struct fb_videomode *mode; +@@ -2108,7 +2098,7 @@ static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) + /* HDMI Initialization Steps D, E, F */ + switch (edid_status) { + case HDMI_EDID_SUCCESS: +- mxc_hdmi_edid_rebuild_modelist(hdmi); ++ mxc_hdmi_create_modelist(hdmi, true); + break; + + /* Nothing to do if EDID same */ +@@ -2120,7 +2110,7 @@ static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) + /* No break here */ + case HDMI_EDID_NO_MODES: + default: +- mxc_hdmi_default_modelist(hdmi); ++ mxc_hdmi_create_modelist(hdmi, false); + break; + } + +@@ -2676,7 +2666,6 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp, + struct mxc_dispdrv_setting *setting) + { + int ret = 0; +- u32 i; + const struct fb_videomode *mode; + struct fb_videomode m; + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp); +@@ -2787,31 +2776,17 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp, + + spin_lock_init(&hdmi->irq_lock); + +- /* Set the default mode and modelist when disp init. */ ++ /* Create default modelist */ ++ mxc_hdmi_create_modelist(hdmi, false); ++ ++ /* Set the default mode when disp init. */ + fb_find_mode(&hdmi->fbi->var, hdmi->fbi, + hdmi->dft_mode_str, NULL, 0, NULL, + hdmi->default_bpp); +- +- console_lock(); +- +- fb_destroy_modelist(&hdmi->fbi->modelist); +- +- /*Add all no interlaced CEA mode to default modelist */ +- for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) { +- mode = &mxc_cea_mode[i]; +- if (mode->xres != 0) { +- struct fb_videomode m = *mode; +- m.flag |= FB_MODE_IS_STANDARD; +- fb_add_videomode(&m, &hdmi->fbi->modelist); +- } +- } +- +- console_unlock(); +- +- /* Find a nearest mode in default modelist */ + fb_var_to_videomode(&m, &hdmi->fbi->var); + hdmi->dft_mode_set = false; + ++ /* Find a nearest mode in default modelist */ + mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist); + if (!mode) { + pr_err("%s: could not find mode in modelist\n", __func__); +-- +1.9.1 + + +============================================================== +file 1111-video-mxc_hdmi-Consider-modes-that-differ-only-in-as.patch +============================================================== + +From 9b245791da35efed7d3745ca5ca35d6cc73b49de Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 08:44:50 +0100 +Subject: [PATCH] video: mxc_hdmi: Consider modes that differ only in aspect + ratio as duplicate + +Certain CEA modes differ from each other only by the aspect ratio. If an EDID +indicates support for both modes of such an otherwise identical pair, we create +a mode list entry only for the first one. This is done because our sysfs cannot +distinguish them. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_hdmi.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index f71c1dd..182ae2a 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -1949,7 +1949,7 @@ static void mxc_hdmi_notify_fb(struct mxc_hdmi *hdmi, bool force_all) + static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + { + struct fb_videomode mode; +- int i, vic, mode_count = ARRAY_SIZE(mxc_cea_mode); ++ int i, j, skip, vic, mode_count = ARRAY_SIZE(mxc_cea_mode); + const struct fb_videomode *mode_data = mxc_cea_mode; + + if (from_edid) { +@@ -1975,6 +1975,19 @@ static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + + mode = mode_data[i]; + ++ /* for dual aspect ratio modes, insert the first one only */ ++ if (mode.vmode & FB_VMODE_ASPECT_MASK) { ++ skip = 0; ++ for (j = i - 1; !skip && j >= 0; j--) { ++ skip = mode.xres == mode_data[j].xres && ++ mode.yres == mode_data[j].yres && ++ mode.refresh == mode_data[j].refresh && ++ (mode.vmode ^ FB_VMODE_ASPECT_MASK) == mode_data[j].vmode; ++ } ++ if (skip) ++ continue; ++ } ++ + /* TODO: Discuss if we should always set default modes as standard */ + if (!from_edid /*&& ignore_edid*/) + mode.flag |= FB_MODE_IS_STANDARD; +-- +1.9.1 + + +============================================================== +file 1112-video-mxc_hdmi-Insert-standard-VGA-mode-only-once.patch +============================================================== + +From 2e980a57c261407795511d4794c8d22e78ecb9b2 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Mon, 4 Jan 2016 08:41:22 +0100 +Subject: [PATCH] video: mxc_hdmi: Insert standard VGA mode only once + +Skip standard VGA if found in EDID. We force this mode to be present +by default and therefore should not add it a second time. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_hdmi.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index 182ae2a..ec4a438 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -95,7 +95,7 @@ + * in HDMI Initialization Step B + */ + static const struct fb_videomode vga_mode = { +- /* 640x480 @ 60 Hz, 31.5 kHz hsync */ ++ /* 640x480 @ 59.94 Hz, 31.5 kHz hsync */ + NULL, 60, 640, 480, 39721, 48, 16, 33, 10, 96, 2, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, FB_MODE_IS_VESA, + }; +@@ -1988,6 +1988,10 @@ static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + continue; + } + ++ /* Skip standard VGA (already present) */ ++ if (vic == 1 && (mode.flag & FB_MODE_IS_VESA)) ++ continue; ++ + /* TODO: Discuss if we should always set default modes as standard */ + if (!from_edid /*&& ignore_edid*/) + mode.flag |= FB_MODE_IS_STANDARD; +-- +1.9.1 + + +============================================================== +file 1113-video-mxc_hdmi-mxc_edid-Introduce-fractional-modes.patch +============================================================== + +From 7df36826253b618c3d44d245b2f1e074112b91c3 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 09:26:40 +0100 +Subject: [PATCH] video: mxc_hdmi/mxc_edid: Introduce fractional modes + +In order to support fractional refresh rates (23.976, 29.97, 59.94, 119.88Hz) +we create 'synthetic' modes. These have the same timing as the corresponding +non-fractional modes (i.e. 24, 30, 60 and 120Hz). However, the refresh rate +is set to 23, 29, 59 and 119, respectively. In addition they have the mode +bit FB_VMODE_FRACTIONAL set. This bit is taken in acount when calculating +the real pixel clock. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_edid.c | 15 ++++++++++----- + drivers/video/mxc/mxc_hdmi.c | 25 +++++++++++++++++++++++-- + 2 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/drivers/video/mxc/mxc_edid.c b/drivers/video/mxc/mxc_edid.c +index 1aaaa68..b3a6ee1 100644 +--- a/drivers/video/mxc/mxc_edid.c ++++ b/drivers/video/mxc/mxc_edid.c +@@ -218,9 +218,9 @@ int mxc_edid_fb_mode_is_equal(bool use_aspect, + u32 mask; + + if (use_aspect) +- mask = ~0; ++ mask = ~FB_VMODE_FRACTIONAL; + else +- mask = ~FB_VMODE_ASPECT_MASK; ++ mask = ~(FB_VMODE_FRACTIONAL | FB_VMODE_ASPECT_MASK); + + return (mode1->xres == mode2->xres && + mode1->yres == mode2->yres && +@@ -823,7 +823,12 @@ const struct fb_videomode *mxc_fb_find_nearest_mode(const struct fb_videomode *m + struct fb_videomode *cmode; + static struct fb_videomode *best; + static u32 diff, diff_refresh; +- u32 mask = relax ? FB_VMODE_MASK_SIMPLE | FB_VMODE_ASPECT_MASK : ~0; ++ u32 mask = relax ? ~FB_VMODE_ASPECT_MASK : ~0; ++ int refresh = mode->refresh; ++ ++ if ((mode->flag & FB_MODE_IS_FROM_VAR) && ++ (mode->vmode & FB_VMODE_FRACTIONAL)) ++ refresh--; + + if (!relax) { + diff = -1; +@@ -844,10 +849,10 @@ const struct fb_videomode *mxc_fb_find_nearest_mode(const struct fb_videomode *m + abs(cmode->yres - mode->yres); + if (diff > d) { + diff = d; +- diff_refresh = abs(cmode->refresh - mode->refresh); ++ diff_refresh = abs(cmode->refresh - refresh); + best = cmode; + } else if (diff == d) { +- d = abs(cmode->refresh - mode->refresh); ++ d = abs(cmode->refresh - refresh); + if (diff_refresh > d) { + diff_refresh = d; + best = cmode; +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index ec4a438..6156e16 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -1999,9 +1999,30 @@ static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + if (fb_add_videomode(&mode, &hdmi->fbi->modelist)) + continue; + +- dev_dbg(&hdmi->pdev->dev, "Added mode: %d, vic: %d", i, vic); + dev_dbg(&hdmi->pdev->dev, +- "xres = %d, yres = %d, scan = %c, ratio = %s, freq = %d, vmode = %d, flag = %d\n", ++ "Mode: vic=%d, xres=%d, yres=%d, scan=%c, ratio=%s, freq=%d, vmode=%d, flag=%d\n", ++ vic, ++ mode.xres, ++ mode.yres, ++ mode.vmode & FB_VMODE_INTERLACED ? 'i' : 'p', ++ mode.vmode & FB_VMODE_ASPECT_4_3 ? "4/3" : ++ mode.vmode & FB_VMODE_ASPECT_16_9 ? "16/9" : "n/a", ++ mode.refresh, ++ mode.vmode, ++ mode.flag); ++ ++ /* check if fractional mode should be inserted */ ++ if (vic == 0 || !(mode.refresh == 24 || (mode.refresh % 30) == 0)) ++ continue; ++ ++ mode.refresh--; ++ mode.vmode |= FB_VMODE_FRACTIONAL; ++ if (fb_add_videomode(&mode, &hdmi->fbi->modelist)) ++ continue; ++ ++ dev_dbg(&hdmi->pdev->dev, ++ "Mode: vic=%d, xres=%d, yres=%d, scan=%c, ratio=%s, freq=%d, vmode=%d, flag=%d\n", ++ vic, + mode.xres, + mode.yres, + mode.vmode & FB_VMODE_INTERLACED ? 'i' : 'p', +-- +1.9.1 + + +============================================================== +file 1114-video-mxc_edid-Adjust-pixel-timings.patch +============================================================== + +From cec6f4f51f22cd0324f255cb99a85eaa7f3d0d78 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 09:51:31 +0100 +Subject: [PATCH] video: mxc_edid: Adjust pixel timings + +Our approach for fractional mode support requires the pixel timings +in the CEA mode table to describe the non-fractional modes. This +patch sets this for the modes that were defined otherwise. +Also it tweaks the rounding when calculating the real pixel clock +from the pixel time specified in the table. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_edid.c | 19 ++++++++++++------- + include/video/mxc_edid.h | 4 ++-- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/drivers/video/mxc/mxc_edid.c b/drivers/video/mxc/mxc_edid.c +index b3a6ee1..edfd6e8 100644 +--- a/drivers/video/mxc/mxc_edid.c ++++ b/drivers/video/mxc/mxc_edid.c +@@ -38,20 +38,25 @@ + #define DPRINTK(fmt, args...) + #endif + ++/* ++ * Attention: pixel times for the fractional mode entries must ++ * specify the non-fractional frequency of that mode! ++ * I.e. 60Hz instead of 59.94 and 24Hz instead of 23.98. ++ */ + const struct fb_videomode mxc_cea_mode[64] = { + /* #1: 640x480p@59.94/60Hz 4:3 */ + [1] = { +- NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0, ++ NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #2: 720x480p@59.94/60Hz 4:3 */ + [2] = { +- NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, ++ NULL, 60, 720, 480, 37000, 60, 16, 30, 9, 62, 6, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #3: 720x480p@59.94/60Hz 16:9 */ + [3] = { +- NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, ++ NULL, 60, 720, 480, 37000, 60, 16, 30, 9, 62, 6, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0, + }, + /* #4: 1280x720p@59.94/60Hz 16:9 */ +@@ -68,22 +73,22 @@ const struct fb_videomode mxc_cea_mode[64] = { + }, + /* #6: 720(1440)x480iH@59.94/60Hz 4:3 */ + [6] = { +- NULL, 60, 1440, 480, 37037, 38, 114, 8, 31, 124, 6, 0, ++ NULL, 60, 1440, 480, 37000, 38, 114, 8, 31, 124, 6, 0, + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #7: 720(1440)x480iH@59.94/60Hz 16:9 */ + [7] = { +- NULL, 60, 1440, 480, 37037, 38, 114, 8, 31, 124, 6, 0, ++ NULL, 60, 1440, 480, 37000, 38, 114, 8, 31, 124, 6, 0, + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0, + }, + /* #8: 720(1440)x240pH@59.94/60Hz 4:3 */ + [8] = { +- NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0, ++ NULL, 60, 1440, 240, 37000, 114, 38, 15, 4, 124, 3, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #9: 720(1440)x240pH@59.94/60Hz 16:9 */ + [9] = { +- NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0, ++ NULL, 60, 1440, 240, 37000, 114, 38, 15, 4, 124, 3, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0, + }, + /* #14: 1440x480p@59.94/60Hz 4:3 */ +diff --git a/include/video/mxc_edid.h b/include/video/mxc_edid.h +index 561fe61..2feed16 100644 +--- a/include/video/mxc_edid.h ++++ b/include/video/mxc_edid.h +@@ -100,8 +100,8 @@ struct mxc_edid_cfg { + }; + + static inline unsigned long mxcPICOS2KHZ(u32 pixclock, u32 vmode) { +- u32 x = (1000000000UL / (pixclock) * 1000 / ((vmode & FB_VMODE_FRACTIONAL) ? 1001 : 1000)); +- return x + ((1000000000UL % x) > (x / 2) ? 1 : 0); ++ return ((((vmode & FB_VMODE_FRACTIONAL) ? ++ (999000999UL*4) : (1000000000UL*4)) / pixclock) + 1) >> 2; + } + + int mxc_edid_var_to_vic(struct fb_var_screeninfo *var); +-- +1.9.1 + + +============================================================== +file 1115-video-mxc_ipuv3_fb-Adjust-IPU-pixelclock.patch +============================================================== + +From 8b308a05dbfdbdffaf632857bc70a6005f95a6f5 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Tue, 29 Dec 2015 17:13:54 +0100 +Subject: [PATCH] video: mxc_ipuv3_fb: Adjust IPU pixelclock + +Use 'fractional' pixelclock calculation for IPU as well. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_ipuv3_fb.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c +index 9a3764f..8856c32 100644 +--- a/drivers/video/mxc/mxc_ipuv3_fb.c ++++ b/drivers/video/mxc/mxc_ipuv3_fb.c +@@ -49,6 +49,7 @@ + #include + #include + ++#include