diff options
author | Chris Conley <cconley@phytec.com> | 2013-08-06 15:57:43 -0700 |
---|---|---|
committer | Anthony Felice <tony.felice@timesys.com> | 2013-09-17 14:22:14 -0400 |
commit | c3f595da0584c68148623af8cb1d4b2f769305a7 (patch) | |
tree | e416622a7cfc09f5fe2a4d2604ca9b34af23bfb2 /drivers | |
parent | 145626078f6ed903c95fbbf1883d4d3d70433c92 (diff) |
pcl052: Cosmic board init and configuration support
Signed-off-by: Chris Conley <cconley@phytec.com>
Signed-off-by: Russell Robinson <rrobinson@phytec.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/hub.c | 4 | ||||
-rw-r--r-- | drivers/video/Kconfig | 7 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/mvf-tda1998x.c | 221 | ||||
-rw-r--r-- | drivers/video/mvf-tda1998x.h | 268 | ||||
-rw-r--r-- | drivers/video/mvf_dcu.c | 85 |
6 files changed, 566 insertions, 20 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f056707d0986..5fa3206886df 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1674,7 +1674,7 @@ void usb_disconnect(struct usb_device **pdev) udev->devnum); #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) { fsl_platform_set_usb0_phy_dis(NULL, 0); fsl_platform_set_usb1_phy_dis(NULL, 0); @@ -2929,7 +2929,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, } #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) { fsl_platform_set_usb0_phy_dis(NULL, 1); fsl_platform_set_usb1_phy_dis(NULL, 1); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ca65437de427..fefbd85e97a0 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1961,6 +1961,13 @@ config FB_MVF_DCU ---help--- Framebuffer driver for the Faraday SoC DCU +config MVF_TDA_998X + depends on FB_MVF_DCU && I2C + tristate "TDA998X HDMI Support" + default n + ---help--- + TDA1998x HDMI Encoder support for MVF FB + config MVF_DCU_BLANKING_TEST bool "DCU framebuffer blanking support" depends on FB && ARCH_MVF && FB_MVF_DCU diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ed2fa59a726e..d420d828ee14 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -123,6 +123,7 @@ obj-$(CONFIG_FB_S3C) += s3c-fb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o obj-$(CONFIG_FB_MVF_DCU) += mvf_dcu.o +obj-$(CONFIG_MVF_TDA_998X) += mvf-tda1998x.o obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ diff --git a/drivers/video/mvf-tda1998x.c b/drivers/video/mvf-tda1998x.c new file mode 100644 index 000000000000..79f92250f215 --- /dev/null +++ b/drivers/video/mvf-tda1998x.c @@ -0,0 +1,221 @@ +/* + * File: dvf-tda1998x.c + * + * Description: This file contains condensed support for the TDA1998X HDMI codec required for display + * from the Freescale Vybrid DCU4 output. It assumes the i2c adapter access routines are available. + */ +// CNC TODO Header? + +//TODO Pare this down CNC +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <asm/mach-types.h> +#include <mach/mvf.h> +#include <mach/mvf-dcu-fb.h> + +//Required +#include <linux/i2c.h> +#include "mvf-tda1998x.h" + + +/* Global Data */ +static struct i2c_adapter *g_i2c_adapter = NULL; +static u8 g_u8_curr_page = 0; + +/* Static Functions */ +static void +set_page(uint16_t reg) +{ + if (REG2PAGE(reg) != g_u8_curr_page) { + uint8_t buf[2] = { REG_CURPAGE, REG2PAGE(reg) }; + struct i2c_msg msg = {TDA1998X_I2C_HDMI_SA, 0, sizeof(buf), buf}; + int ret; + + ret = i2c_transfer(g_i2c_adapter, &msg, 1); + if (ret < 0) + { + printk(KERN_ERR "Error %d writing to REG_CURPAGE\n", ret); + } + else + { + g_u8_curr_page = REG2PAGE(reg); + } + } +} + +static void +reg_write(uint16_t reg, uint8_t val) +{ + uint8_t buf[2] = {REG2ADDR(reg), val}; + int ret; + struct i2c_msg msg = {TDA1998X_I2C_HDMI_SA, 0, sizeof(buf), buf}; + + set_page(reg); + + ret = i2c_transfer(g_i2c_adapter, &msg, 1); + if (ret < 0) + printk(KERN_ERR "Error %d writing to 0x%x\n", ret, reg); +} + +static uint8_t +reg_read(uint16_t reg) +{ + uint8_t u8addr = REG2ADDR(reg); + uint8_t u8ret = 0; + int ret; + struct i2c_msg rgMsg[] = {/* slaveaddr, flags, len, buf */ + {TDA1998X_I2C_HDMI_SA, 0, sizeof(u8addr), &u8addr}, + {TDA1998X_I2C_HDMI_SA, I2C_M_RD, sizeof(u8ret), &u8ret}}; + + /* Change the register page to the one we want */ + set_page(reg); + + ret = i2c_transfer(g_i2c_adapter, rgMsg, 2); + if (ret < 0) + { + printk(KERN_ERR "<%s> Error %d reading from 0x%x\n", __func__, ret, reg); + return 0; + } + else + { + return u8ret; + } +} + +static void +reg_set(uint16_t reg, uint8_t val) +{ + reg_write(reg, reg_read(reg) | val); +} + +static void +reg_clear(uint16_t reg, uint8_t val) +{ + reg_write(reg, reg_read(reg) & ~val); +} + +static bool +tda1998x_init_encoder(void) +{ + int ret; + uint8_t rgBuf[][2] = { /* Register Address, Register Value */ + {REG_CEC_ENAMODS, (CEC_ENAMODS_EN_RXSENS + | CEC_ENAMODS_EN_HDMI)}, + {REG_CEC_FRO_IM_CLK_CTRL, (CEC_FRO_IM_CLK_CTRL_GHOST_DIS + | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL)}, + {REG_CEC_ENAMODS, (CEC_ENAMODS_EN_CEC_CLK + | CEC_ENAMODS_EN_RXSENS + | CEC_ENAMODS_EN_HDMI + | CEC_ENAMODS_EN_CEC)} + }; + struct i2c_msg rgMsg[] = + { + /* slaveaddr,flags,len,buf */ + {TDA1998X_I2C_CEC_SA, 0, sizeof(rgBuf[0]), rgBuf[0]}, + {TDA1998X_I2C_CEC_SA, 0, sizeof(rgBuf[1]), rgBuf[1]}, + {TDA1998X_I2C_CEC_SA, 0, sizeof(rgBuf[2]), rgBuf[2]}, + }; + + /* Initialize the HDMI interface, otherwise the HDMI I2C I/F is off */ + ret = i2c_transfer(g_i2c_adapter, &rgMsg[0], 1); + if (ret < 0) + goto ret_error; + + /* + * Begin Reset Sequence + */ + /* reset audio and i2c master: */ + reg_set(REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); + msleep(50); + reg_clear(REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); + msleep(50); + + /* reset transmitter */ + reg_set(REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); + reg_clear(REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); + + /* PLL registers common configuration */ + reg_write(REG_PLL_SERIAL_1, 0x00); + reg_write(REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1)); + reg_write(REG_PLL_SERIAL_3, 0x00); + reg_write(REG_SERIALIZER, 0x00); + reg_write(REG_BUFFER_OUT, 0x00); + reg_write(REG_PLL_SCG1, 0x00); + reg_write(REG_AUDIO_DIV, 0x03); + reg_write(REG_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); + reg_write(REG_PLL_SCGN1, 0xfa); + reg_write(REG_PLL_SCGN2, 0x00); + reg_write(REG_PLL_SCGR1, 0x5b); + reg_write(REG_PLL_SCGR2, 0x00); + reg_write(REG_PLL_SCG2, 0x10); + /* + * End Reset Sequence + */ + + /* Enable DDC */ + reg_write(REG_DDC_DISABLE, 0x00); + + /* Set clock on DDC channel */ + reg_write(REG_TX3, 39); + + /* Initialize CEC Interface */ + ret = i2c_transfer(g_i2c_adapter, &rgMsg[1], 1); + if (ret < 0) + goto ret_error; + + /* Enable DPMS */ + /* enable video ports */ + reg_write(REG_ENA_VP_0, 0xff); + reg_write(REG_ENA_VP_1, 0xff); + reg_write(REG_ENA_VP_2, 0xff); + /* set muxing after enabling ports: */ + /* Set to RGB 3x 8-bit per 7.2.3 mappings */ + reg_write(REG_VIP_CNTRL_0, 0x23); + reg_write(REG_VIP_CNTRL_1, 0x01); + reg_write(REG_VIP_CNTRL_2, 0x45); + + /* Enable HDMI Encoding */ + ret = i2c_transfer(g_i2c_adapter, &rgMsg[2], 1); + if (ret < 0) + goto ret_error; + + reg_write(REG_TX33, TX33_HDMI); + reg_write(REG_TBG_CNTRL_1, 0x7c); + + return true; + +ret_error: + printk(KERN_ERR "<%s> HDMI I2C I/F failed (%d)\n", __func__, ret); + return false; +} /* tda1998x_init_encoder */ + +/* Public Functions */ +bool init_tda19988(void) +{ + /* Get the handle to the i2c channel */ + g_i2c_adapter = i2c_get_adapter(TDA1998X_I2C_BUS); + if (g_i2c_adapter == NULL) + { + printk(KERN_ERR "<%s> CEC I2C Adapter not found\n", __func__); + return false; + } + return tda1998x_init_encoder(); +} + diff --git a/drivers/video/mvf-tda1998x.h b/drivers/video/mvf-tda1998x.h new file mode 100644 index 000000000000..5a1ebf397c39 --- /dev/null +++ b/drivers/video/mvf-tda1998x.h @@ -0,0 +1,268 @@ +/* + * File: dvf-tda1998x.h + * + * Description: This file contains condensed TDA register defines required to support the + * TDA1998X HDMI codec required for display from the Freescale Vybrid DCU4 output. + * + */ +//CNC TODO: Which header for this? +#ifndef _MVF_TDA1998X_H_ +#define _MVF_TDA1998X_H_ + +/* Public Functions */ +bool init_tda19988(void); + +/* Platform Settings */ +#define EDID_LENGTH 0x80 +#define TDA1998X_I2C_BUS 2 +#define TDA1998X_I2C_CEC_SA 0x34 +#define TDA1998X_I2C_HDMI_SA 0x70 + +/* Device versions: */ +#define TDA9989N2 0x0101 +#define TDA19989 0x0201 +#define TDA19989N2 0x0202 +#define TDA19988 0x0301 + +/* The TDA9988 series of devices use a paged register scheme.. to simplify + * things we encode the page # in upper bits of the register #. To read/ + * write a given register, we need to make sure CURPAGE register is set + * appropriately. Which implies reads/writes are not atomic. Fun! + */ + +#define REG(page, addr) (((page) << 8) | (addr)) +#define REG2ADDR(reg) ((reg) & 0xff) +#define REG2PAGE(reg) (((reg) >> 8) & 0xff) + +#define REG_CURPAGE 0xff /* write */ + +/* Page 00h: General Control */ +#define REG_VERSION_LSB REG(0x00, 0x00) /* read */ +#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */ +# define MAIN_CNTRL0_SR (1 << 0) +# define MAIN_CNTRL0_DECS (1 << 1) +# define MAIN_CNTRL0_DEHS (1 << 2) +# define MAIN_CNTRL0_CECS (1 << 3) +# define MAIN_CNTRL0_CEHS (1 << 4) +# define MAIN_CNTRL0_SCALER (1 << 7) +#define REG_VERSION_MSB REG(0x00, 0x02) /* read */ +#define REG_SOFTRESET REG(0x00, 0x0a) /* write */ +# define SOFTRESET_AUDIO (1 << 0) +# define SOFTRESET_I2C_MASTER (1 << 1) +#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */ +#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */ +#define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */ +# define I2C_MASTER_DIS_MM (1 << 0) +# define I2C_MASTER_DIS_FILT (1 << 1) +# define I2C_MASTER_APP_STRT_LAT (1 << 2) +#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ +#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ +#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ +# define INT_FLAGS_2_EDID_BLK_RD (1 << 1) +#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ +#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ +#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ +#define REG_ENA_AP REG(0x00, 0x1e) /* read/write */ +#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */ +# define VIP_CNTRL_0_MIRR_A (1 << 7) +# define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4) +# define VIP_CNTRL_0_MIRR_B (1 << 3) +# define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0) +#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */ +# define VIP_CNTRL_1_MIRR_C (1 << 7) +# define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4) +# define VIP_CNTRL_1_MIRR_D (1 << 3) +# define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0) +#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */ +# define VIP_CNTRL_2_MIRR_E (1 << 7) +# define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4) +# define VIP_CNTRL_2_MIRR_F (1 << 3) +# define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0) +#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */ +# define VIP_CNTRL_3_X_TGL (1 << 0) +# define VIP_CNTRL_3_H_TGL (1 << 1) +# define VIP_CNTRL_3_V_TGL (1 << 2) +# define VIP_CNTRL_3_EMB (1 << 3) +# define VIP_CNTRL_3_SYNC_DE (1 << 4) +# define VIP_CNTRL_3_SYNC_HS (1 << 5) +# define VIP_CNTRL_3_DE_INT (1 << 6) +# define VIP_CNTRL_3_EDGE (1 << 7) +#define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */ +# define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0) +# define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2) +# define VIP_CNTRL_4_CCIR656 (1 << 4) +# define VIP_CNTRL_4_656_ALT (1 << 5) +# define VIP_CNTRL_4_TST_656 (1 << 6) +# define VIP_CNTRL_4_TST_PAT (1 << 7) +#define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */ +# define VIP_CNTRL_5_CKCASE (1 << 0) +# define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1) + +#define REG_MUX_AP REG(0x00, 0x26) +# define MUX_AP_SELECT_I2S (0x64) +#define REG_MAT_CONTRL REG(0x00, 0x80) /* write */ +# define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0) +# define MAT_CONTRL_MAT_BP (1 << 2) +#define REG_VIDFORMAT REG(0x00, 0xa0) /* write */ +#define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */ +#define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */ +#define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */ +#define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */ +#define REG_NPIX_MSB REG(0x00, 0xa5) /* write */ +#define REG_NPIX_LSB REG(0x00, 0xa6) /* write */ +#define REG_NLINE_MSB REG(0x00, 0xa7) /* write */ +#define REG_NLINE_LSB REG(0x00, 0xa8) /* write */ +#define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */ +#define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */ +#define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */ +#define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */ +#define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */ +#define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */ +#define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */ +#define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */ +#define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */ +#define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */ +#define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */ +#define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */ +#define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */ +#define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */ +#define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */ +#define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */ +#define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */ +#define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */ +#define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */ +#define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */ +#define REG_DE_START_MSB REG(0x00, 0xc5) /* write */ +#define REG_DE_START_LSB REG(0x00, 0xc6) /* write */ +#define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */ +#define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */ +#define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */ +# define TBG_CNTRL_0_FRAME_DIS (1 << 5) +# define TBG_CNTRL_0_SYNC_MTHD (1 << 6) +# define TBG_CNTRL_0_SYNC_ONCE (1 << 7) +#define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */ +# define TBG_CNTRL_1_VH_TGL_0 (1 << 0) +# define TBG_CNTRL_1_VH_TGL_1 (1 << 1) +# define TBG_CNTRL_1_VH_TGL_2 (1 << 2) +# define TBG_CNTRL_1_VHX_EXT_DE (1 << 3) +# define TBG_CNTRL_1_VHX_EXT_HS (1 << 4) +# define TBG_CNTRL_1_VHX_EXT_VS (1 << 5) +# define TBG_CNTRL_1_DWIN_DIS (1 << 6) +#define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */ +#define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */ +# define HVF_CNTRL_0_SM (1 << 7) +# define HVF_CNTRL_0_RWB (1 << 6) +# define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2) +# define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0) +#define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */ +# define HVF_CNTRL_1_FOR (1 << 0) +# define HVF_CNTRL_1_YUVBLK (1 << 1) +# define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2) +# define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4) +# define HVF_CNTRL_1_SEMI_PLANAR (1 << 6) +#define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */ +#define REG_I2S_FORMAT REG(0x00, 0xfc) +#define REG_AIP_CLKSEL REG(0x00, 0xfd) +# define SEL_AIP_I2S (1 << 3) /* I2S Clk */ + +/* Page 02h: PLL settings */ +#define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */ +# define PLL_SERIAL_1_SRL_FDN (1 << 0) +# define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1) +# define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6) +#define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */ +# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0) +# define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4) +#define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */ +# define PLL_SERIAL_3_SRL_CCIR (1 << 0) +# define PLL_SERIAL_3_SRL_DE (1 << 2) +# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4) +#define REG_SERIALIZER REG(0x02, 0x03) /* read/write */ +#define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */ +#define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */ +#define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */ +#define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */ +#define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */ +#define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */ +#define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */ +#define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */ +#define REG_SEL_CLK REG(0x02, 0x11) /* read/write */ +# define SEL_CLK_SEL_CLK1 (1 << 0) +# define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1) +# define SEL_CLK_ENA_SC_CLK (1 << 3) +#define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */ + + +/* Page 09h: EDID Control */ +#define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */ +/* next 127 successive registers are the EDID block */ +#define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */ +#define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */ +#define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */ +#define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */ +#define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */ + +/* Page 10h: information frames and packets */ +#define REG_AVI_IF REG(0x10, 0x40) /* AVI Infoframe packet */ +#define REG_AUDIO_IF REG(0x10, 0x80) /* AVI Infoframe packet */ + +/* Page 11h: audio settings and content info packets */ +#define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */ +# define AIP_CNTRL_0_RST_FIFO (1 << 0) +# define AIP_CNTRL_0_SWAP (1 << 1) +# define AIP_CNTRL_0_LAYOUT (1 << 2) +# define AIP_CNTRL_0_ACR_MAN (1 << 5) +# define AIP_CNTRL_0_RST_CTS (1 << 6) +#define REG_ACR_CTS_0 REG(0x11, 0x05) +#define REG_ACR_CTS_1 REG(0x11, 0x06) +#define REG_ACR_CTS_2 REG(0x11, 0x07) +#define REG_ACR_N_0 REG(0x11, 0x08) +#define REG_ACR_N_1 REG(0x11, 0x09) +#define REG_ACR_N_2 REG(0x11, 0x0a) +#define REG_GC_AVMUTE REG(0x11, 0x0b) +# define GC_AVMUTE_CLRMUTE (1 << 0) +# define GC_AVMUTE_SETMUTE (1 << 1) +#define REG_CTS_N REG(0x11, 0x0c) +#define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */ +# define ENC_CNTRL_RST_ENC (1 << 0) +# define ENC_CNTRL_RST_SEL (1 << 1) +# define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2) +#define REG_DIP_FLAGS REG(0x11, 0x0e) +# define DIP_FLAGS_ACR (1 << 0) +#define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */ +#define DIP_IF_FLAGS_IF1 (1 << 1) +#define DIP_IF_FLAGS_IF2 (1 << 2) +#define DIP_IF_FLAGS_IF3 (1 << 3) +#define DIP_IF_FLAGS_IF4 (1 << 4) +#define DIP_IF_FLAGS_IF5 (1 << 5) + +/* Page 12h: HDCP and OTP */ +#define REG_TX3 REG(0x12, 0x9a) /* read/write */ +#define REG_TX33 REG(0x12, 0xb8) /* read/write */ +# define TX33_HDMI (1 << 1) + + +/* Page 13h: Gamut related metadata packets */ + +/* CEC registers: (not paged) + */ +#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */ +# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) +# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6) +# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1) +# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0) +#define REG_CEC_RXSHPDLEV 0xfe /* read */ +# define CEC_RXSHPDLEV_RXSENS (1 << 0) +# define CEC_RXSHPDLEV_HPD (1 << 1) + +#define REG_CEC_ENAMODS 0xff /* read/write */ +# define CEC_ENAMODS_EN_CEC_CLK (1 << 7) +# define CEC_ENAMODS_DIS_FRO (1 << 6) +# define CEC_ENAMODS_DIS_CCLK (1 << 5) +# define CEC_ENAMODS_EN_WD (1 << 4) +# define CEC_ENAMODS_CEC_INV (1 << 3) +# define CEC_ENAMODS_EN_RXSENS (1 << 2) +# define CEC_ENAMODS_EN_HDMI (1 << 1) +# define CEC_ENAMODS_EN_CEC (1 << 0) + +#endif /*_MVF_TDA1998X_H_*/ diff --git a/drivers/video/mvf_dcu.c b/drivers/video/mvf_dcu.c index 71c271278bce..34661beb5b8a 100644 --- a/drivers/video/mvf_dcu.c +++ b/drivers/video/mvf_dcu.c @@ -32,10 +32,12 @@ #include <asm/mach-types.h> #include <mach/mvf.h> #include <mach/mvf-dcu-fb.h> +#include "mvf-tda1998x.h" - +#define DCU_MASTER_CLOCK_FREQ 226000000 #define DRIVER_NAME "mvf-dcu" + static struct fb_videomode __devinitdata mvf_dcu_default_mode = { .xres = 800, .yres = 480, @@ -52,19 +54,6 @@ static struct fb_videomode __devinitdata mvf_dcu_default_mode = { static struct fb_videomode __devinitdata mvf_dcu_mode_db[] = { { - .name = "480x272", - .xres = 480, - .yres = 272, - .left_margin = 2, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 41, - .vsync_len = 2, - .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - .vmode = FB_VMODE_NONINTERLACED, - }, - { .name = "pm070wl4", .xres = 800, .yres = 480, @@ -77,6 +66,41 @@ static struct fb_videomode __devinitdata mvf_dcu_mode_db[] = { .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, .vmode = FB_VMODE_NONINTERLACED, +#if (defined CONFIG_MACH_PCL052) + },{ + /* HDMI */ + .name = "640x480p_hdmipc", + .pixclock = 25111, /* From TDA Doc */ + .xres = 640, + .yres = 480, + .left_margin = 1, + .right_margin = 1, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 158, + .vsync_len = 36, + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | + FB_SYNC_HOR_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + },{ + /* HDMI 480p */ /* NOTE: Sync isn't valid on this config */ + .name = "720x480p", + .pixclock = 28250, /* VESA is 27.027MHz, DCU docs say 28.250, actual is 28.282MHz*/ + .xres = 720, + .yres = 480, + /* 178 total for 31500Hz hsync */ + .left_margin = 96, /*hbp*/ + .right_margin = 9, /*hfp*/ + .hsync_len = 73, /*hsw*/ + /* 45 total for 59.98 Hz vsync */ + .upper_margin = 1, /*vbp*/ + .lower_margin = 1, /*vfp*/ + .vsync_len = 43, /*vsw*/ + + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT + | FB_SYNC_HOR_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, +#endif /* CONFIG_MACH_PCL052 */ }, }; @@ -395,6 +419,7 @@ static void update_lcdc(struct fb_info *info) struct fb_var_screeninfo *var = &info->var; struct mfb_info *mfbi = info->par; struct mvf_dcu_fb_data *dcu = mfbi->parent; + uint8_t div_val = 0; if (mfbi->type == DCU_TYPE_OFF) { mvf_dcu_disable_panel(info); @@ -429,10 +454,31 @@ static void update_lcdc(struct fb_info *info) DCU_VSYN_PARA_FP(var->lower_margin), dcu->base + DCU_VSYN_PARA); + + /* Setup Default Colorbars RGB format */ + writel(0xFFFF0000, dcu->base + DCU_COLBAR_1); /* red */ + writel(0xFF00FF00, dcu->base + DCU_COLBAR_2); /* green */ + writel(0xFF0000FF, dcu->base + DCU_COLBAR_3); /* blue */ + writel(0xFF00FFFF, dcu->base + DCU_COLBAR_4); /* cyan */ + writel(0xFFFF00FF, dcu->base + DCU_COLBAR_5); /* magenta */ + writel(0xFFFFFF00, dcu->base + DCU_COLBAR_6); /* yellow */ + writel(0xFF000000, dcu->base + DCU_COLBAR_7); /* black */ + writel(0xFFFFFFFF, dcu->base + DCU_COLBAR_8); /* white */ writel(DCU_MODE_BLEND_ITER(3) | DCU_MODE_RASTER_EN(1), dcu->base + DCU_DCU_MODE); - writel(2, dcu->base + DCU_DIV_RATIO); + /* PCLK output calculation */ + if ((var->pixclock == 0) || (DCU_MASTER_CLOCK_FREQ / (var->pixclock<<12) > 0x100)) + { + /* default value */ + div_val = 0x10; + } + else + { + div_val = DCU_MASTER_CLOCK_FREQ / var->pixclock; + } + + writel(div_val, dcu->base + DCU_DIV_RATIO); writel(DCU_SYN_POL_INV_PXCK(0) | DCU_SYN_POL_NEG(0) | DCU_SYN_POL_INV_VS(1) | DCU_SYN_POL_INV_HS(1), @@ -636,9 +682,9 @@ static int mvf_dcu_pan_display(struct fb_var_screeninfo *var, static int mvf_dcu_blank(int blank_mode, struct fb_info *info) { +#ifdef CONFIG_MVF_DCU_BLANKING_TEST struct mfb_info *mfbi = info->par; -#ifdef CONFIG_MVF_DCU_BLANKING_TEST mfbi->blank = blank_mode; switch (blank_mode) { @@ -952,7 +998,8 @@ static int mvf_dcu_resume(struct platform_device *pdev) #else #define mvf_dcu_suspend NULL #define mvf_dcu_resume NULL -#endif +#endif /* CONFIG_PM */ + static int __devinit mvf_dcu_probe(struct platform_device *pdev) { @@ -1043,7 +1090,9 @@ static int __devinit mvf_dcu_probe(struct platform_device *pdev) goto failed_install_fb; } } - +#if (defined CONFIG_MVF_TDA_998X) + init_tda19988(); +#endif /* CONFIG_MVF_TDA_998X */ dev_set_drvdata(&pdev->dev, dcu); return 0; |