mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2026-01-27 12:35:36 +01:00
video: fbdev: mxc: add Northwest Logic DSI driver support
Add the framebuffer driver support for the Northwest Logic MIPI DSI controller. Signed-off-by: Fancy Fang <chen.fang@nxp.com> Signed-off-by: Sandor Yu <Sandor.yu@nxp.com> Reviewed-by: Robby Cai <robby.cai@nxp.com> [ Aisheng: squash fixes ] Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> [ Liu Ying: Select BACKLIGHT_CLASS_DEVICE to partially fix LF-9904 ] Signed-off-by: Liu Ying <victor.liu@nxp.com>
This commit is contained in:
parent
e91eaf7730
commit
5186caddfc
|
|
@ -29,3 +29,14 @@ config FB_MXC_OVERLAY
|
|||
default n
|
||||
help
|
||||
Enhanced LCD controller of MXC has overlay function.
|
||||
|
||||
config FB_MXC_MIPI_DSI_NORTHWEST
|
||||
tristate "MXC MIPI_DSI_NORTHWEST"
|
||||
depends on FB_MXC_DISP_FRAMEWORK
|
||||
depends on FB_MXS
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
|
||||
config FB_MXC_EDID
|
||||
depends on FB_MXC && I2C
|
||||
tristate "MXC EDID support"
|
||||
default y
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
obj-$(CONFIG_FB_MXC_DISP_FRAMEWORK) += mxc_dispdrv.o
|
||||
obj-$(CONFIG_FB_MXC_MIPI_DSI_NORTHWEST) += mipi_dsi_northwest.o
|
||||
obj-$(CONFIG_FB_MXC_EDID) += mxc_edid.o
|
||||
|
|
|
|||
167
drivers/video/fbdev/mxc/mipi_dsi.h
Normal file
167
drivers/video/fbdev/mxc/mipi_dsi.h
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
* Copyright 2017 NXP.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
#ifndef __MIPI_DSI_H__
|
||||
#define __MIPI_DSI_H__
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include "mxc_dispdrv.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define mipi_dbg(fmt, ...) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
|
||||
#else
|
||||
#define mipi_dbg(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define DSI_CMD_BUF_MAXSIZE (128)
|
||||
|
||||
#define DSI_NON_BURST_WITH_SYNC_PULSE 0
|
||||
#define DSI_NON_BURST_WITH_SYNC_EVENT 1
|
||||
#define DSI_BURST_MODE 2
|
||||
|
||||
#define DSI_HSA_PKT_OVERHEAD 10
|
||||
#define DSI_HFP_PKT_OVERHEAD 8
|
||||
#define DSI_HBP_PKT_OVERHEAD 14
|
||||
|
||||
/* DPI interface pixel color coding map */
|
||||
enum mipi_dsi_dpi_fmt {
|
||||
MIPI_RGB565_PACKED = 0,
|
||||
MIPI_RGB565_LOOSELY,
|
||||
MIPI_RGB565_CONFIG3,
|
||||
MIPI_RGB666_PACKED,
|
||||
MIPI_RGB666_LOOSELY,
|
||||
MIPI_RGB888,
|
||||
};
|
||||
|
||||
struct mipi_lcd_config {
|
||||
u32 virtual_ch;
|
||||
u32 data_lane_num;
|
||||
/* device max DPHY clock in MHz unit */
|
||||
u32 max_phy_clk;
|
||||
enum mipi_dsi_dpi_fmt dpi_fmt;
|
||||
};
|
||||
|
||||
struct mipi_dsi_info;
|
||||
struct mipi_dsi_lcd_callback {
|
||||
/* callback for lcd panel operation */
|
||||
void (*get_mipi_lcd_videomode)(struct fb_videomode **, int *,
|
||||
struct mipi_lcd_config **);
|
||||
int (*mipi_lcd_setup)(struct mipi_dsi_info *);
|
||||
|
||||
};
|
||||
|
||||
struct mipi_dsi_match_lcd {
|
||||
char *lcd_panel;
|
||||
struct mipi_dsi_lcd_callback lcd_callback;
|
||||
};
|
||||
|
||||
struct mipi_dsi_bus_mux {
|
||||
int reg;
|
||||
int mask;
|
||||
int (*get_mux) (int dev_id, int disp_id);
|
||||
};
|
||||
|
||||
/* driver private data */
|
||||
struct mipi_dsi_info {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *mmio_base;
|
||||
void __iomem *phy_base;
|
||||
struct regmap *regmap;
|
||||
struct regmap *mux_sel;
|
||||
const struct mipi_dsi_bus_mux *bus_mux;
|
||||
int dsi_power_on;
|
||||
int lcd_inited;
|
||||
int encoder;
|
||||
int traffic_mode;
|
||||
u32 dphy_pll_config;
|
||||
int dev_id;
|
||||
int disp_id;
|
||||
char *lcd_panel;
|
||||
int irq;
|
||||
uint32_t phy_ref_clkfreq;
|
||||
#ifdef CONFIG_FB_IMX64
|
||||
struct clk *core_clk;
|
||||
struct clk *phy_ref_clk;
|
||||
struct clk *dbi_clk;
|
||||
struct clk *rxesc_clk;
|
||||
struct clk *txesc_clk;
|
||||
#else
|
||||
struct clk *dphy_clk;
|
||||
struct clk *cfg_clk;
|
||||
struct clk *esc_clk;
|
||||
#endif
|
||||
struct mxc_dispdrv_handle *disp_mipi;
|
||||
int vmode_index;
|
||||
struct fb_videomode *mode;
|
||||
struct regulator *disp_power_on;
|
||||
struct mipi_lcd_config *lcd_config;
|
||||
/* board related power control */
|
||||
struct backlight_device *bl;
|
||||
/* callback for lcd panel operation */
|
||||
struct mipi_dsi_lcd_callback *lcd_callback;
|
||||
|
||||
int (*mipi_dsi_pkt_read)(struct mipi_dsi_info *mipi,
|
||||
u8 data_type, u32 *buf, int len);
|
||||
int (*mipi_dsi_pkt_write)(struct mipi_dsi_info *mipi_dsi,
|
||||
u8 data_type, const u32 *buf, int len);
|
||||
int (*mipi_dsi_dcs_cmd)(struct mipi_dsi_info *mipi,
|
||||
u8 cmd, const u32 *param, int num);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL
|
||||
void mipid_hx8369_get_lcd_videomode(struct fb_videomode **mode, int *size,
|
||||
struct mipi_lcd_config **data);
|
||||
int mipid_hx8369_lcd_setup(struct mipi_dsi_info *);
|
||||
#endif
|
||||
#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5079E
|
||||
void mipid_otm8018b_get_lcd_videomode(struct fb_videomode **mode, int *size,
|
||||
struct mipi_lcd_config **data);
|
||||
int mipid_otm8018b_lcd_setup(struct mipi_dsi_info *);
|
||||
#endif
|
||||
#ifdef CONFIG_FB_MXC_TRULY_PANEL_TFT3P5581E
|
||||
void mipid_hx8363_get_lcd_videomode(struct fb_videomode **mode, int *size,
|
||||
struct mipi_lcd_config **data);
|
||||
int mipid_hx8363_lcd_setup(struct mipi_dsi_info *);
|
||||
#endif
|
||||
#ifdef CONFIG_FB_MXC_RK_PANEL_RK055AHD042
|
||||
void mipid_rm68200_get_lcd_videomode(struct fb_videomode **mode, int *size,
|
||||
struct mipi_lcd_config **data);
|
||||
int mipid_rm68200_lcd_setup(struct mipi_dsi_info *mipi_dsi);
|
||||
#endif
|
||||
#ifdef CONFIG_FB_MXC_RK_PANEL_RK055IQH042
|
||||
void mipid_rm68191_get_lcd_videomode(struct fb_videomode **mode, int *size,
|
||||
struct mipi_lcd_config **data);
|
||||
int mipid_rm68191_lcd_setup(struct mipi_dsi_info *mipi_dsi);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1556
drivers/video/fbdev/mxc/mipi_dsi_northwest.c
Normal file
1556
drivers/video/fbdev/mxc/mipi_dsi_northwest.c
Normal file
File diff suppressed because it is too large
Load Diff
770
drivers/video/fbdev/mxc/mxc_edid.c
Normal file
770
drivers/video/fbdev/mxc/mxc_edid.c
Normal file
|
|
@ -0,0 +1,770 @@
|
|||
/*
|
||||
* Copyright 2009-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file mxc_edid.c
|
||||
*
|
||||
* @brief MXC EDID driver
|
||||
*
|
||||
* @ingroup Framebuffer
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Include files
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fb.h>
|
||||
#include <video/mxc_edid.h>
|
||||
#include "../edid.h"
|
||||
|
||||
#undef DEBUG /* define this for verbose EDID parsing output */
|
||||
#ifdef DEBUG
|
||||
#define DPRINTK(fmt, args...) printk(fmt, ## args)
|
||||
#else
|
||||
#define DPRINTK(fmt, args...)
|
||||
#endif
|
||||
|
||||
const struct fb_videomode mxc_cea_mode[64] = {
|
||||
/* #1: 640x480p@59.94/60Hz 4:3 */
|
||||
[1] = {
|
||||
NULL, 60, 640, 480, 39683, 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,
|
||||
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,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #4: 1280x720p@59.94/60Hz 16:9 */
|
||||
[4] = {
|
||||
NULL, 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
|
||||
},
|
||||
/* #5: 1920x1080i@59.94/60Hz 16:9 */
|
||||
[5] = {
|
||||
NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #6: 720(1440)x480iH@59.94/60Hz 4:3 */
|
||||
[6] = {
|
||||
NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
|
||||
FB_VMODE_INTERLACED | FB_VMODE_ASPECT_4_3, 0,
|
||||
},
|
||||
/* #7: 720(1440)x480iH@59.94/60Hz 16:9 */
|
||||
[7] = {
|
||||
NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 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,
|
||||
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,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #14: 1440x480p@59.94/60Hz 4:3 */
|
||||
[14] = {
|
||||
NULL, 60, 1440, 480, 18500, 120, 32, 30, 9, 124, 6, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
|
||||
},
|
||||
/* #15: 1440x480p@59.94/60Hz 16:9 */
|
||||
[15] = {
|
||||
NULL, 60, 1440, 480, 18500, 120, 32, 30, 9, 124, 6, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #16: 1920x1080p@60Hz 16:9 */
|
||||
[16] = {
|
||||
NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #17: 720x576pH@50Hz 4:3 */
|
||||
[17] = {
|
||||
NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
|
||||
},
|
||||
/* #18: 720x576pH@50Hz 16:9 */
|
||||
[18] = {
|
||||
NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #19: 1280x720p@50Hz */
|
||||
[19] = {
|
||||
NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #20: 1920x1080i@50Hz */
|
||||
[20] = {
|
||||
NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #23: 720(1440)x288pH@50Hz 4:3 */
|
||||
[23] = {
|
||||
NULL, 50, 1440, 288, 37037, 138, 24, 19, 2, 126, 3, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
|
||||
},
|
||||
/* #24: 720(1440)x288pH@50Hz 16:9 */
|
||||
[24] = {
|
||||
NULL, 50, 1440, 288, 37037, 138, 24, 19, 2, 126, 3, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #29: 720(1440)x576pH@50Hz 4:3 */
|
||||
[29] = {
|
||||
NULL, 50, 1440, 576, 18518, 136, 24, 39, 5, 128, 5, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0,
|
||||
},
|
||||
/* #30: 720(1440)x576pH@50Hz 16:9 */
|
||||
[30] = {
|
||||
NULL, 50, 1440, 576, 18518, 136, 24, 39, 5, 128, 5, 0,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #31: 1920x1080p@50Hz */
|
||||
[31] = {
|
||||
NULL, 50, 1920, 1080, 6734, 148, 528, 36, 4, 44, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #32: 1920x1080p@23.98/24Hz */
|
||||
[32] = {
|
||||
NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #33: 1920x1080p@25Hz */
|
||||
[33] = {
|
||||
NULL, 25, 1920, 1080, 13468, 148, 528, 36, 4, 44, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #34: 1920x1080p@30Hz */
|
||||
[34] = {
|
||||
NULL, 30, 1920, 1080, 13468, 148, 88, 36, 4, 44, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0,
|
||||
},
|
||||
/* #41: 1280x720p@100Hz 16:9 */
|
||||
[41] = {
|
||||
NULL, 100, 1280, 720, 6734, 220, 440, 20, 5, 40, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
|
||||
},
|
||||
/* #47: 1280x720p@119.88/120Hz 16:9 */
|
||||
[47] = {
|
||||
NULL, 120, 1280, 720, 6734, 220, 110, 20, 5, 40, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* We have a special version of fb_mode_is_equal that ignores
|
||||
* pixclock, since for many CEA modes, 2 frequencies are supported
|
||||
* e.g. 640x480 @ 60Hz or 59.94Hz
|
||||
*/
|
||||
int mxc_edid_fb_mode_is_equal(bool use_aspect,
|
||||
const struct fb_videomode *mode1,
|
||||
const struct fb_videomode *mode2)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
if (use_aspect)
|
||||
mask = ~0;
|
||||
else
|
||||
mask = ~FB_VMODE_ASPECT_MASK;
|
||||
|
||||
return (mode1->xres == mode2->xres &&
|
||||
mode1->yres == mode2->yres &&
|
||||
mode1->hsync_len == mode2->hsync_len &&
|
||||
mode1->vsync_len == mode2->vsync_len &&
|
||||
mode1->left_margin == mode2->left_margin &&
|
||||
mode1->right_margin == mode2->right_margin &&
|
||||
mode1->upper_margin == mode2->upper_margin &&
|
||||
mode1->lower_margin == mode2->lower_margin &&
|
||||
mode1->sync == mode2->sync &&
|
||||
/* refresh check, 59.94Hz and 60Hz have the same parameter
|
||||
* in struct of mxc_cea_mode */
|
||||
abs(mode1->refresh - mode2->refresh) <= 1 &&
|
||||
(mode1->vmode & mask) == (mode2->vmode & mask));
|
||||
}
|
||||
|
||||
static void get_detailed_timing(unsigned char *block,
|
||||
struct fb_videomode *mode)
|
||||
{
|
||||
mode->xres = H_ACTIVE;
|
||||
mode->yres = V_ACTIVE;
|
||||
mode->pixclock = PIXEL_CLOCK;
|
||||
mode->pixclock /= 1000;
|
||||
mode->pixclock = KHZ2PICOS(mode->pixclock);
|
||||
mode->right_margin = H_SYNC_OFFSET;
|
||||
mode->left_margin = (H_ACTIVE + H_BLANKING) -
|
||||
(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
|
||||
mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
|
||||
V_SYNC_WIDTH;
|
||||
mode->lower_margin = V_SYNC_OFFSET;
|
||||
mode->hsync_len = H_SYNC_WIDTH;
|
||||
mode->vsync_len = V_SYNC_WIDTH;
|
||||
if (HSYNC_POSITIVE)
|
||||
mode->sync |= FB_SYNC_HOR_HIGH_ACT;
|
||||
if (VSYNC_POSITIVE)
|
||||
mode->sync |= FB_SYNC_VERT_HIGH_ACT;
|
||||
mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
|
||||
(V_ACTIVE + V_BLANKING));
|
||||
if (INTERLACED) {
|
||||
mode->yres *= 2;
|
||||
mode->upper_margin *= 2;
|
||||
mode->lower_margin *= 2;
|
||||
mode->vsync_len *= 2;
|
||||
mode->vmode |= FB_VMODE_INTERLACED;
|
||||
}
|
||||
mode->flag = FB_MODE_IS_DETAILED;
|
||||
|
||||
if ((H_SIZE / 16) == (V_SIZE / 9))
|
||||
mode->vmode |= FB_VMODE_ASPECT_16_9;
|
||||
else if ((H_SIZE / 4) == (V_SIZE / 3))
|
||||
mode->vmode |= FB_VMODE_ASPECT_4_3;
|
||||
else if ((mode->xres / 16) == (mode->yres / 9))
|
||||
mode->vmode |= FB_VMODE_ASPECT_16_9;
|
||||
else if ((mode->xres / 4) == (mode->yres / 3))
|
||||
mode->vmode |= FB_VMODE_ASPECT_4_3;
|
||||
|
||||
if (mode->vmode & FB_VMODE_ASPECT_16_9)
|
||||
DPRINTK("Aspect ratio: 16:9\n");
|
||||
if (mode->vmode & FB_VMODE_ASPECT_4_3)
|
||||
DPRINTK("Aspect ratio: 4:3\n");
|
||||
DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
|
||||
DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
|
||||
H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
|
||||
DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
|
||||
V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
|
||||
DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
|
||||
(VSYNC_POSITIVE) ? "+" : "-");
|
||||
}
|
||||
|
||||
int mxc_edid_parse_ext_blk(unsigned char *edid,
|
||||
struct mxc_edid_cfg *cfg,
|
||||
struct fb_monspecs *specs)
|
||||
{
|
||||
char detail_timing_desc_offset;
|
||||
struct fb_videomode *mode, *m;
|
||||
unsigned char index = 0x0;
|
||||
unsigned char *block;
|
||||
int i, num = 0, revision;
|
||||
|
||||
if (edid[index++] != 0x2) /* only support cea ext block now */
|
||||
return 0;
|
||||
revision = edid[index++];
|
||||
DPRINTK("cea extent revision %d\n", revision);
|
||||
mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
|
||||
if (mode == NULL)
|
||||
return -1;
|
||||
|
||||
detail_timing_desc_offset = edid[index++];
|
||||
|
||||
if (revision >= 2) {
|
||||
cfg->cea_underscan = (edid[index] >> 7) & 0x1;
|
||||
cfg->cea_basicaudio = (edid[index] >> 6) & 0x1;
|
||||
cfg->cea_ycbcr444 = (edid[index] >> 5) & 0x1;
|
||||
cfg->cea_ycbcr422 = (edid[index] >> 4) & 0x1;
|
||||
|
||||
DPRINTK("CEA underscan %d\n", cfg->cea_underscan);
|
||||
DPRINTK("CEA basicaudio %d\n", cfg->cea_basicaudio);
|
||||
DPRINTK("CEA ycbcr444 %d\n", cfg->cea_ycbcr444);
|
||||
DPRINTK("CEA ycbcr422 %d\n", cfg->cea_ycbcr422);
|
||||
}
|
||||
|
||||
if (revision >= 3) {
|
||||
/* short desc */
|
||||
DPRINTK("CEA Short desc timmings\n");
|
||||
index++;
|
||||
while (index < detail_timing_desc_offset) {
|
||||
unsigned char tagcode, blklen;
|
||||
|
||||
tagcode = (edid[index] >> 5) & 0x7;
|
||||
blklen = (edid[index]) & 0x1f;
|
||||
|
||||
DPRINTK("Tagcode %x Len %d\n", tagcode, blklen);
|
||||
|
||||
switch (tagcode) {
|
||||
case 0x2: /*Video data block*/
|
||||
{
|
||||
int cea_idx;
|
||||
i = 0;
|
||||
while (i < blklen) {
|
||||
index++;
|
||||
cea_idx = edid[index] & 0x7f;
|
||||
if (cea_idx < ARRAY_SIZE(mxc_cea_mode) &&
|
||||
(mxc_cea_mode[cea_idx].xres)) {
|
||||
DPRINTK("Support CEA Format #%d\n", cea_idx);
|
||||
mode[num] = mxc_cea_mode[cea_idx];
|
||||
mode[num].flag |= FB_MODE_IS_STANDARD;
|
||||
num++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x3: /*Vendor specific data*/
|
||||
{
|
||||
unsigned char IEEE_reg_iden[3];
|
||||
unsigned char deep_color;
|
||||
unsigned char latency_present;
|
||||
unsigned char I_latency_present;
|
||||
unsigned char hdmi_video_present;
|
||||
unsigned char hdmi_3d_present;
|
||||
unsigned char hdmi_3d_multi_present;
|
||||
unsigned char hdmi_vic_len;
|
||||
unsigned char hdmi_3d_len;
|
||||
unsigned char index_inc = 0;
|
||||
unsigned char vsd_end;
|
||||
|
||||
vsd_end = index + blklen;
|
||||
|
||||
IEEE_reg_iden[0] = edid[index+1];
|
||||
IEEE_reg_iden[1] = edid[index+2];
|
||||
IEEE_reg_iden[2] = edid[index+3];
|
||||
cfg->physical_address[0] = (edid[index+4] & 0xf0) >> 4;
|
||||
cfg->physical_address[1] = (edid[index+4] & 0x0f);
|
||||
cfg->physical_address[2] = (edid[index+5] & 0xf0) >> 4;
|
||||
cfg->physical_address[3] = (edid[index+5] & 0x0f);
|
||||
|
||||
if ((IEEE_reg_iden[0] == 0x03) &&
|
||||
(IEEE_reg_iden[1] == 0x0c) &&
|
||||
(IEEE_reg_iden[2] == 0x00))
|
||||
cfg->hdmi_cap = 1;
|
||||
|
||||
if (blklen > 5) {
|
||||
deep_color = edid[index+6];
|
||||
if (deep_color & 0x80)
|
||||
cfg->vsd_support_ai = true;
|
||||
if (deep_color & 0x40)
|
||||
cfg->vsd_dc_48bit = true;
|
||||
if (deep_color & 0x20)
|
||||
cfg->vsd_dc_36bit = true;
|
||||
if (deep_color & 0x10)
|
||||
cfg->vsd_dc_30bit = true;
|
||||
if (deep_color & 0x08)
|
||||
cfg->vsd_dc_y444 = true;
|
||||
if (deep_color & 0x01)
|
||||
cfg->vsd_dvi_dual = true;
|
||||
}
|
||||
|
||||
DPRINTK("VSD hdmi capability %d\n", cfg->hdmi_cap);
|
||||
DPRINTK("VSD support ai %d\n", cfg->vsd_support_ai);
|
||||
DPRINTK("VSD support deep color 48bit %d\n", cfg->vsd_dc_48bit);
|
||||
DPRINTK("VSD support deep color 36bit %d\n", cfg->vsd_dc_36bit);
|
||||
DPRINTK("VSD support deep color 30bit %d\n", cfg->vsd_dc_30bit);
|
||||
DPRINTK("VSD support deep color y444 %d\n", cfg->vsd_dc_y444);
|
||||
DPRINTK("VSD support dvi dual %d\n", cfg->vsd_dvi_dual);
|
||||
|
||||
if (blklen > 6)
|
||||
cfg->vsd_max_tmdsclk_rate = edid[index+7] * 5;
|
||||
DPRINTK("VSD MAX TMDS CLOCK RATE %d\n", cfg->vsd_max_tmdsclk_rate);
|
||||
|
||||
if (blklen > 7) {
|
||||
latency_present = edid[index+8] >> 7;
|
||||
I_latency_present = (edid[index+8] & 0x40) >> 6;
|
||||
hdmi_video_present = (edid[index+8] & 0x20) >> 5;
|
||||
cfg->vsd_cnc3 = (edid[index+8] & 0x8) >> 3;
|
||||
cfg->vsd_cnc2 = (edid[index+8] & 0x4) >> 2;
|
||||
cfg->vsd_cnc1 = (edid[index+8] & 0x2) >> 1;
|
||||
cfg->vsd_cnc0 = edid[index+8] & 0x1;
|
||||
|
||||
DPRINTK("VSD cnc0 %d\n", cfg->vsd_cnc0);
|
||||
DPRINTK("VSD cnc1 %d\n", cfg->vsd_cnc1);
|
||||
DPRINTK("VSD cnc2 %d\n", cfg->vsd_cnc2);
|
||||
DPRINTK("VSD cnc3 %d\n", cfg->vsd_cnc3);
|
||||
DPRINTK("latency_present %d\n", latency_present);
|
||||
DPRINTK("I_latency_present %d\n", I_latency_present);
|
||||
DPRINTK("hdmi_video_present %d\n", hdmi_video_present);
|
||||
|
||||
} else {
|
||||
index += blklen;
|
||||
break;
|
||||
}
|
||||
|
||||
index += 9;
|
||||
|
||||
/*latency present */
|
||||
if (latency_present) {
|
||||
cfg->vsd_video_latency = edid[index++];
|
||||
cfg->vsd_audio_latency = edid[index++];
|
||||
|
||||
if (I_latency_present) {
|
||||
cfg->vsd_I_video_latency = edid[index++];
|
||||
cfg->vsd_I_audio_latency = edid[index++];
|
||||
} else {
|
||||
cfg->vsd_I_video_latency = cfg->vsd_video_latency;
|
||||
cfg->vsd_I_audio_latency = cfg->vsd_audio_latency;
|
||||
}
|
||||
|
||||
DPRINTK("VSD latency video_latency %d\n", cfg->vsd_video_latency);
|
||||
DPRINTK("VSD latency audio_latency %d\n", cfg->vsd_audio_latency);
|
||||
DPRINTK("VSD latency I_video_latency %d\n", cfg->vsd_I_video_latency);
|
||||
DPRINTK("VSD latency I_audio_latency %d\n", cfg->vsd_I_audio_latency);
|
||||
}
|
||||
|
||||
if (hdmi_video_present) {
|
||||
hdmi_3d_present = edid[index] >> 7;
|
||||
hdmi_3d_multi_present = (edid[index] & 0x60) >> 5;
|
||||
index++;
|
||||
hdmi_vic_len = (edid[index] & 0xe0) >> 5;
|
||||
hdmi_3d_len = edid[index] & 0x1f;
|
||||
index++;
|
||||
|
||||
DPRINTK("hdmi_3d_present %d\n", hdmi_3d_present);
|
||||
DPRINTK("hdmi_3d_multi_present %d\n", hdmi_3d_multi_present);
|
||||
DPRINTK("hdmi_vic_len %d\n", hdmi_vic_len);
|
||||
DPRINTK("hdmi_3d_len %d\n", hdmi_3d_len);
|
||||
|
||||
if (hdmi_vic_len > 0) {
|
||||
for (i = 0; i < hdmi_vic_len; i++) {
|
||||
cfg->hdmi_vic[i] = edid[index++];
|
||||
DPRINTK("HDMI_vic=%d\n", cfg->hdmi_vic[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (hdmi_3d_len > 0) {
|
||||
if (hdmi_3d_present) {
|
||||
if (hdmi_3d_multi_present == 0x1) {
|
||||
cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
|
||||
index_inc = 2;
|
||||
} else if (hdmi_3d_multi_present == 0x2) {
|
||||
cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
|
||||
cfg->hdmi_3d_mask_all = (edid[index+2] << 8) | edid[index+3];
|
||||
index_inc = 4;
|
||||
} else
|
||||
index_inc = 0;
|
||||
}
|
||||
|
||||
DPRINTK("HDMI 3d struct all =0x%x\n", cfg->hdmi_3d_struct_all);
|
||||
DPRINTK("HDMI 3d mask all =0x%x\n", cfg->hdmi_3d_mask_all);
|
||||
|
||||
/* Read 2D vic 3D_struct */
|
||||
if ((hdmi_3d_len - index_inc) > 0) {
|
||||
DPRINTK("Support 3D video format\n");
|
||||
i = 0;
|
||||
while ((hdmi_3d_len - index_inc) > 0) {
|
||||
|
||||
cfg->hdmi_3d_format[i].vic_order_2d = edid[index+index_inc] >> 4;
|
||||
cfg->hdmi_3d_format[i].struct_3d = edid[index+index_inc] & 0x0f;
|
||||
index_inc++;
|
||||
|
||||
if (cfg->hdmi_3d_format[i].struct_3d == 8) {
|
||||
cfg->hdmi_3d_format[i].detail_3d = edid[index+index_inc] >> 4;
|
||||
index_inc++;
|
||||
} else if (cfg->hdmi_3d_format[i].struct_3d > 8) {
|
||||
cfg->hdmi_3d_format[i].detail_3d = 0;
|
||||
index_inc++;
|
||||
}
|
||||
|
||||
DPRINTK("vic_order_2d=%d, 3d_struct=%d, 3d_detail=0x%x\n",
|
||||
cfg->hdmi_3d_format[i].vic_order_2d,
|
||||
cfg->hdmi_3d_format[i].struct_3d,
|
||||
cfg->hdmi_3d_format[i].detail_3d);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index = vsd_end;
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x1: /*Audio data block*/
|
||||
{
|
||||
u8 audio_format, max_ch, byte1, byte2, byte3;
|
||||
|
||||
i = 0;
|
||||
cfg->max_channels = 0;
|
||||
cfg->sample_rates = 0;
|
||||
cfg->sample_sizes = 0;
|
||||
|
||||
while (i < blklen) {
|
||||
byte1 = edid[index + 1];
|
||||
byte2 = edid[index + 2];
|
||||
byte3 = edid[index + 3];
|
||||
index += 3;
|
||||
i += 3;
|
||||
|
||||
audio_format = byte1 >> 3;
|
||||
max_ch = (byte1 & 0x07) + 1;
|
||||
|
||||
DPRINTK("Audio Format Descriptor : %2d\n", audio_format);
|
||||
DPRINTK("Max Number of Channels : %2d\n", max_ch);
|
||||
DPRINTK("Sample Rates : %02x\n", byte2);
|
||||
|
||||
/* ALSA can't specify specific compressed
|
||||
* formats, so only care about PCM for now. */
|
||||
if (audio_format == AUDIO_CODING_TYPE_LPCM) {
|
||||
if (max_ch > cfg->max_channels)
|
||||
cfg->max_channels = max_ch;
|
||||
|
||||
cfg->sample_rates |= byte2;
|
||||
cfg->sample_sizes |= byte3 & 0x7;
|
||||
DPRINTK("Sample Sizes : %02x\n",
|
||||
byte3 & 0x7);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x4: /*Speaker allocation block*/
|
||||
{
|
||||
i = 0;
|
||||
while (i < blklen) {
|
||||
cfg->speaker_alloc = edid[index + 1];
|
||||
index += 3;
|
||||
i += 3;
|
||||
DPRINTK("Speaker Alloc : %02x\n", cfg->speaker_alloc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x7: /*User extended block*/
|
||||
default:
|
||||
/* skip */
|
||||
DPRINTK("Not handle block, tagcode = 0x%x\n", tagcode);
|
||||
index += blklen;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/* long desc */
|
||||
DPRINTK("CEA long desc timmings\n");
|
||||
index = detail_timing_desc_offset;
|
||||
block = edid + index;
|
||||
while (index < (EDID_LENGTH - DETAILED_TIMING_DESCRIPTION_SIZE)) {
|
||||
if (!(block[0] == 0x00 && block[1] == 0x00)) {
|
||||
get_detailed_timing(block, &mode[num]);
|
||||
num++;
|
||||
}
|
||||
block += DETAILED_TIMING_DESCRIPTION_SIZE;
|
||||
index += DETAILED_TIMING_DESCRIPTION_SIZE;
|
||||
}
|
||||
|
||||
if (!num) {
|
||||
kfree(mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m = kmalloc((num + specs->modedb_len) *
|
||||
sizeof(struct fb_videomode), GFP_KERNEL);
|
||||
if (!m) {
|
||||
kfree(mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (specs->modedb_len) {
|
||||
memmove(m, specs->modedb,
|
||||
specs->modedb_len * sizeof(struct fb_videomode));
|
||||
kfree(specs->modedb);
|
||||
}
|
||||
memmove(m+specs->modedb_len, mode,
|
||||
num * sizeof(struct fb_videomode));
|
||||
kfree(mode);
|
||||
|
||||
specs->modedb_len += num;
|
||||
specs->modedb = m;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mxc_edid_parse_ext_blk);
|
||||
|
||||
static int mxc_edid_readblk(struct i2c_adapter *adp,
|
||||
unsigned short addr, unsigned char *edid)
|
||||
{
|
||||
int ret = 0, extblknum = 0;
|
||||
unsigned char regaddr = 0x0;
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = ®addr,
|
||||
}, {
|
||||
.addr = addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = EDID_LENGTH,
|
||||
.buf = edid,
|
||||
},
|
||||
};
|
||||
|
||||
ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
|
||||
if (ret != ARRAY_SIZE(msg)) {
|
||||
DPRINTK("unable to read EDID block\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (edid[1] == 0x00)
|
||||
return -ENOENT;
|
||||
|
||||
extblknum = edid[0x7E];
|
||||
|
||||
if (extblknum) {
|
||||
regaddr = 128;
|
||||
msg[1].buf = edid + EDID_LENGTH;
|
||||
|
||||
ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
|
||||
if (ret != ARRAY_SIZE(msg)) {
|
||||
DPRINTK("unable to read EDID ext block\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return extblknum;
|
||||
}
|
||||
|
||||
static int mxc_edid_readsegblk(struct i2c_adapter *adp, unsigned short addr,
|
||||
unsigned char *edid, int seg_num)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char segment = 0x1, regaddr = 0;
|
||||
struct i2c_msg msg[3] = {
|
||||
{
|
||||
.addr = 0x30,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &segment,
|
||||
}, {
|
||||
.addr = addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = ®addr,
|
||||
}, {
|
||||
.addr = addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = EDID_LENGTH,
|
||||
.buf = edid,
|
||||
},
|
||||
};
|
||||
|
||||
ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
|
||||
if (ret != ARRAY_SIZE(msg)) {
|
||||
DPRINTK("unable to read EDID block\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (seg_num == 2) {
|
||||
regaddr = 128;
|
||||
msg[2].buf = edid + EDID_LENGTH;
|
||||
|
||||
ret = i2c_transfer(adp, msg, ARRAY_SIZE(msg));
|
||||
if (ret != ARRAY_SIZE(msg)) {
|
||||
DPRINTK("unable to read EDID block\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxc_edid_var_to_vic(struct fb_var_screeninfo *var)
|
||||
{
|
||||
int i;
|
||||
struct fb_videomode m;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
|
||||
fb_var_to_videomode(&m, var);
|
||||
if (mxc_edid_fb_mode_is_equal(false, &m, &mxc_cea_mode[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(mxc_cea_mode))
|
||||
return 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(mxc_edid_var_to_vic);
|
||||
|
||||
int mxc_edid_mode_to_vic(const struct fb_videomode *mode)
|
||||
{
|
||||
int i;
|
||||
bool use_aspect = (mode->vmode & FB_VMODE_ASPECT_MASK);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
|
||||
if (mxc_edid_fb_mode_is_equal(use_aspect, mode, &mxc_cea_mode[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(mxc_cea_mode))
|
||||
return 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(mxc_edid_mode_to_vic);
|
||||
|
||||
/* make sure edid has 512 bytes*/
|
||||
int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
|
||||
unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi)
|
||||
{
|
||||
int ret = 0, extblknum;
|
||||
if (!adp || !edid || !cfg || !fbi)
|
||||
return -EINVAL;
|
||||
|
||||
memset(edid, 0, EDID_LENGTH*4);
|
||||
memset(cfg, 0, sizeof(struct mxc_edid_cfg));
|
||||
|
||||
extblknum = mxc_edid_readblk(adp, addr, edid);
|
||||
if (extblknum < 0)
|
||||
return extblknum;
|
||||
|
||||
/* edid first block parsing */
|
||||
memset(&fbi->monspecs, 0, sizeof(fbi->monspecs));
|
||||
fb_edid_to_monspecs(edid, &fbi->monspecs);
|
||||
|
||||
if (extblknum) {
|
||||
int i;
|
||||
|
||||
/* FIXME: mxc_edid_readsegblk() won't read more than 2 blocks
|
||||
* and the for-loop will read past the end of the buffer! :-( */
|
||||
if (extblknum > 3) {
|
||||
WARN_ON(true);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* need read segment block? */
|
||||
if (extblknum > 1) {
|
||||
ret = mxc_edid_readsegblk(adp, addr,
|
||||
edid + EDID_LENGTH*2, extblknum - 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 1; i <= extblknum; i++)
|
||||
/* edid ext block parsing */
|
||||
mxc_edid_parse_ext_blk(edid + i*EDID_LENGTH,
|
||||
cfg, &fbi->monspecs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mxc_edid_read);
|
||||
|
||||
164
include/linux/mipi_dsi_northwest.h
Normal file
164
include/linux/mipi_dsi_northwest.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDE_MIPI_DSI_NORTHWEST_H
|
||||
#define __INCLUDE_MIPI_DSI_NORTHWEST_H
|
||||
|
||||
/* ---------------------------- register offsets --------------------------- */
|
||||
|
||||
/* sim */
|
||||
#define SIM_SOPT1 0x0
|
||||
#define MIPI_ISO_DISABLE 0x8
|
||||
|
||||
#define SIM_SOPT1CFG 0x4
|
||||
#define DSI_RST_DPI_N 0x80000000
|
||||
#define DSI_RST_ESC_N 0x40000000
|
||||
#define DSI_RST_BYTE_N 0x20000000
|
||||
#define DSI_SD 0x200
|
||||
#define DSI_CM 0x100
|
||||
#define DSI_PLL_EN 0x80
|
||||
|
||||
/* SRC */
|
||||
#define SRC_MIPIPHY_RCR 0x28
|
||||
#define MIPI_DSI_RESET_BYTE_N 0x2
|
||||
#define MIPI_DSI_RESET_N 0x4
|
||||
#define MIPI_DSI_DPI_RESET_N 0x8
|
||||
#define MIPI_DSI_ESC_RESET_N 0x10
|
||||
#define MIPI_DSI_PCLK_RESET_N 0x20
|
||||
|
||||
/* GPR */
|
||||
#define IOMUXC_GPR_GPR13 0x34
|
||||
#define GPR_MIPI_MUX_SEL 0x4
|
||||
|
||||
/* dphy */
|
||||
#define DPHY_PD_DPHY 0x300
|
||||
#define DPHY_M_PRG_HS_PREPARE 0x304
|
||||
#define DPHY_MC_PRG_HS_PREPARE 0x308
|
||||
#define DPHY_M_PRG_HS_ZERO 0x30c
|
||||
#define DPHY_MC_PRG_HS_ZERO 0x310
|
||||
#define DPHY_M_PRG_HS_TRAIL 0x314
|
||||
#define DPHY_MC_PRG_HS_TRAIL 0x318
|
||||
#define DPHY_PD_PLL 0x31c
|
||||
#define DPHY_TST 0x320
|
||||
#define DPHY_CN 0x324
|
||||
#define DPHY_CM 0x328
|
||||
#define DPHY_CO 0x32c
|
||||
#define DPHY_LOCK 0x330
|
||||
#define DPHY_LOCK_BYP 0x334
|
||||
#define DPHY_RTERM_SEL 0x338
|
||||
#define DPHY_AUTO_PD_EN 0x33c
|
||||
#define DPHY_RXLPRP 0x340
|
||||
#define DPHY_RXCDRP 0x344
|
||||
|
||||
/* host */
|
||||
#define HOST_CFG_NUM_LANES 0x0
|
||||
#define HOST_CFG_NONCONTINUOUS_CLK 0x4
|
||||
#define HOST_CFG_T_PRE 0x8
|
||||
#define HOST_CFG_T_POST 0xc
|
||||
#define HOST_CFG_TX_GAP 0x10
|
||||
#define HOST_CFG_AUTOINSERT_EOTP 0x14
|
||||
#define HOST_CFG_EXTRA_CMDS_AFTER_EOTP 0x18
|
||||
#define HOST_CFG_HTX_TO_COUNT 0x1c
|
||||
#define HOST_CFG_LRX_H_TO_COUNT 0x20
|
||||
#define HOST_CFG_BTA_H_TO_COUNT 0x24
|
||||
#define HOST_CFG_TWAKEUP 0x28
|
||||
#define HOST_CFG_STATUS_OUT 0x2c
|
||||
#define HOST_RX_ERROR_STATUS 0x30
|
||||
|
||||
/* dpi */
|
||||
#define DPI_PIXEL_PAYLOAD_SIZE 0x200
|
||||
#define DPI_PIXEL_FIFO_SEND_LEVEL 0x204
|
||||
#define DPI_INTERFACE_COLOR_CODING 0x208
|
||||
#define DPI_PIXEL_FORMAT 0x20c
|
||||
#define DPI_VSYNC_POLARITY 0x210
|
||||
#define DPI_HSYNC_POLARITY 0x214
|
||||
#define DPI_VIDEO_MODE 0x218
|
||||
#define DPI_HFP 0x21c
|
||||
#define DPI_HBP 0x220
|
||||
#define DPI_HSA 0x224
|
||||
#define DPI_ENABLE_MULT_PKTS 0x228
|
||||
#define DPI_VBP 0x22c
|
||||
#define DPI_VFP 0x230
|
||||
#define DPI_BLLP_MODE 0x234
|
||||
#define DPI_USE_NULL_PKT_BLLP 0x238
|
||||
#define DPI_VACTIVE 0x23c
|
||||
#define DPI_VC 0x240
|
||||
|
||||
/* apb pkt */
|
||||
#define HOST_TX_PAYLOAD 0x280
|
||||
|
||||
#define HOST_PKT_CONTROL 0x284
|
||||
#define HOST_PKT_CONTROL_WC(x) (((x) & 0xffff) << 0)
|
||||
#define HOST_PKT_CONTROL_VC(x) (((x) & 0x3) << 16)
|
||||
#define HOST_PKT_CONTROL_DT(x) (((x) & 0x3f) << 18)
|
||||
#define HOST_PKT_CONTROL_HS_SEL(x) (((x) & 0x1) << 24)
|
||||
#define HOST_PKT_CONTROL_BTA_TX(x) (((x) & 0x1) << 25)
|
||||
#define HOST_PKT_CONTROL_BTA_NO_TX(x) (((x) & 0x1) << 26)
|
||||
|
||||
#define HOST_SEND_PACKET 0x288
|
||||
#define HOST_PKT_STATUS 0x28c
|
||||
#define HOST_PKT_FIFO_WR_LEVEL 0x290
|
||||
#define HOST_PKT_FIFO_RD_LEVEL 0x294
|
||||
#define HOST_PKT_RX_PAYLOAD 0x298
|
||||
|
||||
#define HOST_PKT_RX_PKT_HEADER 0x29c
|
||||
#define HOST_PKT_RX_PKT_HEADER_WC(x) (((x) & 0xffff) << 0)
|
||||
#define HOST_PKT_RX_PKT_HEADER_DT(x) (((x) & 0x3f) << 16)
|
||||
#define HOST_PKT_RX_PKT_HEADER_VC(x) (((x) & 0x3) << 22)
|
||||
|
||||
#define HOST_IRQ_STATUS 0x2a0
|
||||
#define HOST_IRQ_STATUS_SM_NOT_IDLE (1 << 0)
|
||||
#define HOST_IRQ_STATUS_TX_PKT_DONE (1 << 1)
|
||||
#define HOST_IRQ_STATUS_DPHY_DIRECTION (1 << 2)
|
||||
#define HOST_IRQ_STATUS_TX_FIFO_OVFLW (1 << 3)
|
||||
#define HOST_IRQ_STATUS_TX_FIFO_UDFLW (1 << 4)
|
||||
#define HOST_IRQ_STATUS_RX_FIFO_OVFLW (1 << 5)
|
||||
#define HOST_IRQ_STATUS_RX_FIFO_UDFLW (1 << 6)
|
||||
#define HOST_IRQ_STATUS_RX_PKT_HDR_RCVD (1 << 7)
|
||||
#define HOST_IRQ_STATUS_RX_PKT_PAYLOAD_DATA_RCVD (1 << 8)
|
||||
#define HOST_IRQ_STATUS_HOST_BTA_TIMEOUT (1 << 29)
|
||||
#define HOST_IRQ_STATUS_LP_RX_TIMEOUT (1 << 30)
|
||||
#define HOST_IRQ_STATUS_HS_TX_TIMEOUT (1 << 31)
|
||||
|
||||
#define HOST_IRQ_STATUS2 0x2a4
|
||||
#define HOST_IRQ_STATUS2_SINGLE_BIT_ECC_ERR (1 << 0)
|
||||
#define HOST_IRQ_STATUS2_MULTI_BIT_ECC_ERR (1 << 1)
|
||||
#define HOST_IRQ_STATUS2_CRC_ERR (1 << 2)
|
||||
|
||||
#define HOST_IRQ_MASK 0x2a8
|
||||
#define HOST_IRQ_MASK_SM_NOT_IDLE_MASK (1 << 0)
|
||||
#define HOST_IRQ_MASK_TX_PKT_DONE_MASK (1 << 1)
|
||||
#define HOST_IRQ_MASK_DPHY_DIRECTION_MASK (1 << 2)
|
||||
#define HOST_IRQ_MASK_TX_FIFO_OVFLW_MASK (1 << 3)
|
||||
#define HOST_IRQ_MASK_TX_FIFO_UDFLW_MASK (1 << 4)
|
||||
#define HOST_IRQ_MASK_RX_FIFO_OVFLW_MASK (1 << 5)
|
||||
#define HOST_IRQ_MASK_RX_FIFO_UDFLW_MASK (1 << 6)
|
||||
#define HOST_IRQ_MASK_RX_PKT_HDR_RCVD_MASK (1 << 7)
|
||||
#define HOST_IRQ_MASK_RX_PKT_PAYLOAD_DATA_RCVD_MASK (1 << 8)
|
||||
#define HOST_IRQ_MASK_HOST_BTA_TIMEOUT_MASK (1 << 29)
|
||||
#define HOST_IRQ_MASK_LP_RX_TIMEOUT_MASK (1 << 30)
|
||||
#define HOST_IRQ_MASK_HS_TX_TIMEOUT_MASK (1 << 31)
|
||||
|
||||
#define HOST_IRQ_MASK2 0x2ac
|
||||
#define HOST_IRQ_MASK2_SINGLE_BIT_ECC_ERR_MASK (1 << 0)
|
||||
#define HOST_IRQ_MASK2_MULTI_BIT_ECC_ERR_MASK (1 << 1)
|
||||
#define HOST_IRQ_MASK2_CRC_ERR_MASK (1 << 2)
|
||||
|
||||
/* ------------------------------------- end -------------------------------- */
|
||||
|
||||
#endif
|
||||
107
include/video/mxc_edid.h
Normal file
107
include/video/mxc_edid.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright 2009-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file mxc_edid.h
|
||||
*
|
||||
* @brief MXC EDID tools
|
||||
*
|
||||
* @ingroup Framebuffer
|
||||
*/
|
||||
|
||||
#ifndef MXC_EDID_H
|
||||
#define MXC_EDID_H
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#define FB_VMODE_ASPECT_4_3 0x10
|
||||
#define FB_VMODE_ASPECT_16_9 0x20
|
||||
#define FB_VMODE_ASPECT_MASK (FB_VMODE_ASPECT_4_3 | FB_VMODE_ASPECT_16_9)
|
||||
|
||||
enum cea_audio_coding_types {
|
||||
AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
|
||||
AUDIO_CODING_TYPE_LPCM = 1,
|
||||
AUDIO_CODING_TYPE_AC3 = 2,
|
||||
AUDIO_CODING_TYPE_MPEG1 = 3,
|
||||
AUDIO_CODING_TYPE_MP3 = 4,
|
||||
AUDIO_CODING_TYPE_MPEG2 = 5,
|
||||
AUDIO_CODING_TYPE_AACLC = 6,
|
||||
AUDIO_CODING_TYPE_DTS = 7,
|
||||
AUDIO_CODING_TYPE_ATRAC = 8,
|
||||
AUDIO_CODING_TYPE_SACD = 9,
|
||||
AUDIO_CODING_TYPE_EAC3 = 10,
|
||||
AUDIO_CODING_TYPE_DTS_HD = 11,
|
||||
AUDIO_CODING_TYPE_MLP = 12,
|
||||
AUDIO_CODING_TYPE_DST = 13,
|
||||
AUDIO_CODING_TYPE_WMAPRO = 14,
|
||||
AUDIO_CODING_TYPE_RESERVED = 15,
|
||||
};
|
||||
|
||||
struct mxc_hdmi_3d_format {
|
||||
unsigned char vic_order_2d;
|
||||
unsigned char struct_3d;
|
||||
unsigned char detail_3d;
|
||||
unsigned char reserved;
|
||||
};
|
||||
|
||||
struct mxc_edid_cfg {
|
||||
bool cea_underscan;
|
||||
bool cea_basicaudio;
|
||||
bool cea_ycbcr444;
|
||||
bool cea_ycbcr422;
|
||||
bool hdmi_cap;
|
||||
|
||||
/*VSD*/
|
||||
bool vsd_support_ai;
|
||||
bool vsd_dc_48bit;
|
||||
bool vsd_dc_36bit;
|
||||
bool vsd_dc_30bit;
|
||||
bool vsd_dc_y444;
|
||||
bool vsd_dvi_dual;
|
||||
|
||||
bool vsd_cnc0;
|
||||
bool vsd_cnc1;
|
||||
bool vsd_cnc2;
|
||||
bool vsd_cnc3;
|
||||
|
||||
u8 vsd_video_latency;
|
||||
u8 vsd_audio_latency;
|
||||
u8 vsd_I_video_latency;
|
||||
u8 vsd_I_audio_latency;
|
||||
|
||||
u8 physical_address[4];
|
||||
u8 hdmi_vic[64];
|
||||
struct mxc_hdmi_3d_format hdmi_3d_format[64];
|
||||
u16 hdmi_3d_mask_all;
|
||||
u16 hdmi_3d_struct_all;
|
||||
u32 vsd_max_tmdsclk_rate;
|
||||
|
||||
u8 max_channels;
|
||||
u8 sample_sizes;
|
||||
u8 sample_rates;
|
||||
u8 speaker_alloc;
|
||||
};
|
||||
|
||||
extern const struct fb_videomode mxc_cea_mode[64];
|
||||
|
||||
int mxc_edid_var_to_vic(struct fb_var_screeninfo *var);
|
||||
int mxc_edid_mode_to_vic(const struct fb_videomode *mode);
|
||||
int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
|
||||
unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi);
|
||||
int mxc_edid_parse_ext_blk(unsigned char *edid, struct mxc_edid_cfg *cfg,
|
||||
struct fb_monspecs *specs);
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user