From: Srinivas Pulukuru <srinivas.pulukuru@xxxxxx> Add driver for SIL9022 DPI-to-HDMI chip. Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@xxxxxx> [sathyap@xxxxxx: Ported the driver from 2.6.32 based internal kernel to v3.10 kernel] Signed-off-by: Sathya Prakash M R <sathyap@xxxxxx> --- This patch was tested using the legacy OMAP3630 based Zoom3 platform. There is no DT support for Zoom , hence board file changes made locally were used for validation purpose. Further, DT support will be added for a newer SOC which uses the sil9022 HDMI interface chip. drivers/video/omap2/displays/Kconfig | 8 + drivers/video/omap2/displays/Makefile | 1 + drivers/video/omap2/displays/panel-sil9022.c | 1274 ++++++++++++++++++++++++++ drivers/video/omap2/displays/panel-sil9022.h | 527 +++++++++++ 4 files changed, 1810 insertions(+) create mode 100644 drivers/video/omap2/displays/panel-sil9022.c create mode 100644 drivers/video/omap2/displays/panel-sil9022.h diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index c3853c9..53d8bb7 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -39,6 +39,14 @@ config PANEL_NEC_NL8048HL11_01B This NEC NL8048HL11-01B panel is TFT LCD used in the Zoom2/3/3630 sdp boards. +config PANEL_SIL9022 + tristate "HDMI interface" + depends on OMAP2_DSS_DPI + depends on I2C + help + Driver for SIL9022 DPI-to-HDMI chip + Driver uses i2c to read EDID information. + config PANEL_PICODLP tristate "TI PICO DLP mini-projector" depends on OMAP2_DSS_DPI && I2C diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index 58a5176..34cfa8e 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o +obj-$(CONFIG_PANEL_SIL9022) += panel-sil9022.o obj-$(CONFIG_PANEL_TAAL) += panel-taal.o obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o diff --git a/drivers/video/omap2/displays/panel-sil9022.c b/drivers/video/omap2/displays/panel-sil9022.c new file mode 100644 index 0000000..3b5cb17 --- /dev/null +++ b/drivers/video/omap2/displays/panel-sil9022.c @@ -0,0 +1,1274 @@ +/* + * drivers/video/omap2/panel-sil9022.c + * + * Copyright (C) 2009 Texas Instruments + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + * SIL9022 hdmi driver + * Owner: kiran Chitriki + * + */ + +/***********************************/ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/i2c.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> + +#include <video/omapdss.h> +#include <video/omap-panel-data.h> +#include "panel-sil9022.h" + +u16 current_descriptor_addrs; + +static struct i2c_client *sil9022_client; + +static struct omap_video_timings omap_dss_hdmi_timings = { + .x_res = HDMI_XRES, + .y_res = HDMI_YRES, + .pixel_clock = HDMI_PIXCLOCK_MAX, + .hfp = 110, + .hbp = 220, + .hsw = 40, + .vfp = 5, + .vbp = 20, + .vsw = 5, + .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, + .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, + .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, + .de_level = OMAPDSS_SIG_ACTIVE_HIGH, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, +}; + +static struct hdmi_reg_data hdmi_tpi_audio_config_data[] = { + /* Transmitter is brought to Full operation when value of power + * state register is 0x0 */ + { HDMI_TPI_POWER_STATE_CTRL_REG, TPI_AVI_POWER_STATE_D0 }, + /* TMDS output lines active. bit 3 1:TMDS inactive, 0: TMDS active */ + { HDMI_SYS_CTRL_DATA_REG, 0x01 }, + /*HDCP Enable - Disable */ + { HDMI_TPI_HDCP_CONTROLDATA_REG, 0 }, + /* I2S mode , Mute Enabled , PCM */ + { HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, TPI_AUDIO_INTERFACE_I2S | + TPI_AUDIO_MUTE_ENABLE | + TPI_AUDIO_CODING_PCM }, + /* I2S Input configuration register */ + { HDMI_TPI_I2S_INPUT_CONFIG_REG, TPI_I2S_SCK_EDGE_RISING | + TPI_I2S_MCLK_MULTIPLIER_256 | + TPI_I2S_WS_POLARITY_HIGH | + TPI_I2S_SD_JUSTIFY_LEFT | + TPI_I2S_SD_DIRECTION_MSB_FIRST | + TPI_I2S_FIRST_BIT_SHIFT_YES }, + /* I2S Enable ad Mapping Register */ + { HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_ENABLE | + TPI_I2S_SD_FIFO_0 | + TPI_I2S_DOWNSAMPLE_DISABLE | + TPI_I2S_LF_RT_SWAP_NO | + TPI_I2S_SD_CONFIG_SELECT_SD0 }, + { HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE | + TPI_I2S_SD_FIFO_1 | + TPI_I2S_DOWNSAMPLE_DISABLE | + TPI_I2S_LF_RT_SWAP_NO | + TPI_I2S_SD_CONFIG_SELECT_SD1 }, + { HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE | + TPI_I2S_SD_FIFO_2 | + TPI_I2S_DOWNSAMPLE_DISABLE | + TPI_I2S_LF_RT_SWAP_NO | + TPI_I2S_SD_CONFIG_SELECT_SD2 }, + { HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE | + TPI_I2S_SD_FIFO_3 | + TPI_I2S_DOWNSAMPLE_DISABLE | + TPI_I2S_LF_RT_SWAP_NO | + TPI_I2S_SD_CONFIG_SELECT_SD3 }, + { HDMI_TPI_AUDIO_CONFIG_BYTE3_REG, TPI_AUDIO_SAMPLE_SIZE_16 | + TPI_AUDIO_FREQ_44KHZ | + TPI_AUDIO_2_CHANNEL }, + /* Speaker Configuration refer CEA Specification*/ + { HDMI_TPI_AUDIO_CONFIG_BYTE4_REG, (0x0 << 0)}, + /* Stream Header Settings */ + { HDMI_TPI_I2S_STRM_HDR_0_REG, I2S_CHAN_STATUS_MODE }, + { HDMI_TPI_I2S_STRM_HDR_1_REG, I2S_CHAN_STATUS_CAT_CODE }, + { HDMI_TPI_I2S_STRM_HDR_2_REG, I2S_CHAN_SOURCE_CHANNEL_NUM }, + { HDMI_TPI_I2S_STRM_HDR_3_REG, I2S_CHAN_ACCURACY_N_44_SAMPLING_FS }, + { HDMI_TPI_I2S_STRM_HDR_4_REG, I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH }, + /* Infoframe data Select */ + { HDMI_CPI_MISC_IF_SELECT_REG, HDMI_INFOFRAME_TX_ENABLE | + HDMI_INFOFRAME_TX_REPEAT | + HDMI_AUDIO_INFOFRAME }, +}; + +static u8 misc_audio_info_frame_data[] = { + MISC_INFOFRAME_TYPE | MISC_INFOFRAME_ALWAYS_SET, + MISC_INFOFRAME_VERSION, + MISC_INFOFRAME_LENGTH, + 0, /* Checksum byte*/ + HDMI_SH_PCM | HDMI_SH_TWO_CHANNELS, + HDMI_SH_44KHz | HDMI_SH_16BIT, /* 44.1 KHz*/ + 0x0, /* Default 0*/ + HDMI_SH_SPKR_FLFR, + HDMI_SH_0dB_ATUN | 0x1, /* 0 dB Attenuation*/ + 0x0, + 0x0, + 0x0, + 0x0, + 0x0 +}; + +static u8 avi_info_frame_data[] = { + 0x00, + 0x00, + 0xA8, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +void get_horz_vert_timing_info(u8 *edid) +{ + /*HORIZONTAL FRONT PORCH */ + omap_dss_hdmi_timings.hfp = edid[current_descriptor_addrs + 8]; + /*HORIZONTAL SYNC WIDTH */ + omap_dss_hdmi_timings.hsw = edid[current_descriptor_addrs + 9]; + /*HORIZONTAL BACK PORCH */ + omap_dss_hdmi_timings.hbp = (((edid[current_descriptor_addrs + 4] + & 0x0F) << 8) | + edid[current_descriptor_addrs + 3]) - + (omap_dss_hdmi_timings.hfp + omap_dss_hdmi_timings.hsw); + /*VERTICAL FRONT PORCH */ + omap_dss_hdmi_timings.vfp = ((edid[current_descriptor_addrs + 10] & + 0xF0) >> 4); + /*VERTICAL SYNC WIDTH */ + omap_dss_hdmi_timings.vsw = (edid[current_descriptor_addrs + 10] & + 0x0F); + /*VERTICAL BACK PORCH */ + omap_dss_hdmi_timings.vbp = (((edid[current_descriptor_addrs + 7] & + 0x0F) << 8) | + edid[current_descriptor_addrs + 6]) - + (omap_dss_hdmi_timings.vfp + omap_dss_hdmi_timings.vsw); + + dev_dbg(&sil9022_client->dev, "<%s>\n" + "hfp = %d\n" + "hsw = %d\n" + "hbp = %d\n" + "vfp = %d\n" + "vsw = %d\n" + "vbp = %d\n", + __func__, + omap_dss_hdmi_timings.hfp, + omap_dss_hdmi_timings.hsw, + omap_dss_hdmi_timings.hbp, + omap_dss_hdmi_timings.vfp, + omap_dss_hdmi_timings.vsw, + omap_dss_hdmi_timings.vbp + ); + +} + +void get_edid_timing_data(u8 *edid, u16 *pixel_clk, u16 *horizontal_res, + u16 *vertical_res) +{ + u8 offset, effective_addrs; + u8 count; + u8 i; + u8 flag = false; + /*check for 720P timing in block0 */ + for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { + current_descriptor_addrs = + EDID_DESCRIPTOR_BLOCK0_ADDRESS + + count * EDID_TIMING_DESCRIPTOR_SIZE; + *horizontal_res = + (((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 4 + + count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) | + edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 2 + + count * EDID_TIMING_DESCRIPTOR_SIZE]); + *vertical_res = + (((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 7 + + count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) | + edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 5 + + count * EDID_TIMING_DESCRIPTOR_SIZE]); + + dev_dbg(&sil9022_client->dev, + "<%s> ***Block-0-Timing-descriptor[%d]***\n", + __func__, count); + for (i = current_descriptor_addrs; + i < + (current_descriptor_addrs+EDID_TIMING_DESCRIPTOR_SIZE); + i++) + dev_dbg(&sil9022_client->dev, + "%x ==> %x\n", i, edid[i]); + + dev_dbg(&sil9022_client->dev, + "<%s>\n" + "E-EDID Buffer Index = %d\n" + "horizontal_res = %d\n" + "vertical_res = %d\n", + __func__, + current_descriptor_addrs, + *horizontal_res, + *vertical_res + ); + + if (*horizontal_res == HDMI_XRES && + *vertical_res == HDMI_YRES) { + dev_info(&sil9022_client->dev, + "<%s>\nFound EDID Data for %d x %dp\n", + __func__, *horizontal_res, *vertical_res); + flag = true; + break; + } + } + + /*check for the Timing in block1 */ + if (flag != true) { + offset = edid[EDID_DESCRIPTOR_BLOCK1_ADDRESS + 2]; + if (offset != 0) { + effective_addrs = EDID_DESCRIPTOR_BLOCK1_ADDRESS + + offset; + /*to determine the number of descriptor blocks */ + for (count = 0; + count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; + count++) { + current_descriptor_addrs = effective_addrs + + count * EDID_TIMING_DESCRIPTOR_SIZE; + *horizontal_res = + (((edid[effective_addrs + 4 + + count*EDID_TIMING_DESCRIPTOR_SIZE] & + 0xF0) << 4) | + edid[effective_addrs + 2 + + count * EDID_TIMING_DESCRIPTOR_SIZE]); + *vertical_res = + (((edid[effective_addrs + 7 + + count*EDID_TIMING_DESCRIPTOR_SIZE] & + 0xF0) << 4) | + edid[effective_addrs + 5 + + count * EDID_TIMING_DESCRIPTOR_SIZE]); + + dev_dbg(&sil9022_client->dev, + "<%s> Block1-Timing-descriptor[%d]\n", + __func__, count); + + for (i = current_descriptor_addrs; + i < (current_descriptor_addrs+ + EDID_TIMING_DESCRIPTOR_SIZE); i++) + dev_dbg(&sil9022_client->dev, + "%x ==> %x\n", + i, edid[i]); + + dev_dbg(&sil9022_client->dev, "<%s>\n" + "current_descriptor = %d\n" + "horizontal_res = %d\n" + "vertical_res = %d\n", + __func__, current_descriptor_addrs, + *horizontal_res, *vertical_res); + + if (*horizontal_res == HDMI_XRES && + *vertical_res == HDMI_YRES) { + dev_info(&sil9022_client->dev, + "<%s> Found EDID Data for " + "%d x %dp\n", + __func__, + *horizontal_res, + *vertical_res + ); + flag = true; + break; + } + } + } + } + + if (flag == true) { + *pixel_clk = ((edid[current_descriptor_addrs + 1] << 8) | + edid[current_descriptor_addrs]); + + omap_dss_hdmi_timings.x_res = *horizontal_res; + omap_dss_hdmi_timings.y_res = *vertical_res; + omap_dss_hdmi_timings.pixel_clock = *pixel_clk*10; + dev_dbg(&sil9022_client->dev, + "EDID TIMING DATA supported by zoom2 FOUND\n" + "EDID DTD block address = %d\n" + "pixel_clk = %d\n" + "horizontal res = %d\n" + "vertical res = %d\n", + current_descriptor_addrs, + omap_dss_hdmi_timings.pixel_clock, + omap_dss_hdmi_timings.x_res, + omap_dss_hdmi_timings.y_res + ); + + get_horz_vert_timing_info(edid); + } else { + + dev_info(&sil9022_client->dev, + "<%s>\n" + "EDID TIMING DATA supported by zoom2 NOT FOUND\n" + "setting default timing values for 720p\n" + "pixel_clk = %d\n" + "horizontal res = %d\n" + "vertical res = %d\n", + __func__, + omap_dss_hdmi_timings.pixel_clock, + omap_dss_hdmi_timings.x_res, + omap_dss_hdmi_timings.y_res + ); + + *pixel_clk = omap_dss_hdmi_timings.pixel_clock; + *horizontal_res = omap_dss_hdmi_timings.x_res; + *vertical_res = omap_dss_hdmi_timings.y_res; + } + + +} + + +static int +sil9022_blockwrite_reg(struct i2c_client *client, + u8 reg, u16 alength, u8 *val, u16 *out_len) +{ + int err = 0, i; + struct i2c_msg msg[1]; + u8 data[2]; + + if (!client->adapter) { + dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); + return -ENODEV; + } + + msg->addr = client->addr; + msg->flags = I2C_M_WR; + msg->len = 2; + msg->buf = data; + + /* high byte goes out first */ + data[0] = reg >> 8; + + for (i = 0; i < alength - 1; i++) { + data[1] = val[i]; + err = i2c_transfer(client->adapter, msg, 1); + udelay(50); + dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, " + "*val=%d flags=%d byte[%d] err=%d\n", + __func__, data[0], data[1], msg->flags, i, err); + if (err < 0) + break; + } + /* set the number of bytes written*/ + *out_len = i; + + if (err < 0) { + dev_err(&client->dev, "<%s> ERROR: i2c Block Write at 0x%x, " + "*val=%d flags=%d bytes written=%d " + "err=%d\n", + __func__, data[0], data[1], msg->flags, i, err); + return err; + } + return 0; +} + +static int +sil9022_blockread_reg(struct i2c_client *client, + u16 data_length, u16 alength, + u8 reg, u8 *val, u16 *out_len) +{ + int err = 0, i; + struct i2c_msg msg[1]; + u8 data[2]; + + if (!client->adapter) { + dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); + return -ENODEV; + } + + msg->addr = client->addr; + msg->flags = I2C_M_WR; + msg->len = 1; + msg->buf = data; + + /* High byte goes out first */ + data[0] = reg; + err = i2c_transfer(client->adapter, msg, 1); + dev_dbg(&client->dev, "<%s> i2c Block Read1 at 0x%x, " + "*val=%d flags=%d err=%d\n", + __func__, data[0], data[1], msg->flags, err); + + for (i = 0; i < alength; i++) { + if (err >= 0) { + mdelay(3); + msg->flags = I2C_M_RD; + msg->len = data_length; + err = i2c_transfer(client->adapter, msg, 1); + } else + break; + if (err >= 0) { + val[i] = 0; + /* High byte comes first */ + if (data_length == 1) + val[i] = data[0]; + else if (data_length == 2) + val[i] = data[1] + (data[0] << 8); + dev_dbg(&client->dev, "<%s> i2c Block Read2 at 0x%x, " + "*val=%d flags=%d byte=%d " + "err=%d\n", + __func__, reg, val[i], msg->flags, i, err); + } else + break; + } + *out_len = i; + dev_dbg(&client->dev, "<%s> i2c Block Read at 0x%x, bytes read = %d\n", + __func__, client->addr, *out_len); + + if (err < 0) { + dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, " + "*val=%d flags=%d bytes read=%d err=%d\n", + __func__, reg, *val, msg->flags, i, err); + return err; + } + return 0; +} + + +/* Write a value to a register in sil9022 device. + * @client: i2c driver client structure. + * @reg: Address of the register to read value from. + * @val: Value to be written to a specific register. + * Returns zero if successful, or non-zero otherwise. + */ +static int +sil9022_write_reg(struct i2c_client *client, u8 reg, u8 val) +{ + int err = 0; + struct i2c_msg msg[1]; + u8 data[2]; + int retries = 0; + + if (!client->adapter) { + dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); + return -ENODEV; + } + +retry: + msg->addr = client->addr; + msg->flags = I2C_M_WR; + msg->len = 2; + msg->buf = data; + + data[0] = reg; + data[1] = val; + + err = i2c_transfer(client->adapter, msg, 1); + dev_dbg(&client->dev, "<%s> i2c write at=%x " + "val=%x flags=%d err=%d\n", + __func__, data[0], data[1], msg->flags, err); + udelay(50); + + if (err >= 0) + return 0; + + dev_err(&client->dev, "<%s> ERROR: i2c write at=%x " + "val=%x flags=%d err=%d\n", + __func__, data[0], data[1], msg->flags, err); + if (retries <= 5) { + dev_info(&client->dev, "Retrying I2C... %d\n", retries); + retries++; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(20)); + goto retry; + } + return err; +} + +/* + * Read a value from a register in sil9022 device. + * The value is returned in 'val'. + * Returns zero if successful, or non-zero otherwise. + */ +static int +sil9022_read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val) +{ + int err = 0; + struct i2c_msg msg[1]; + u8 data[2]; + + if (!client->adapter) { + dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__); + return -ENODEV; + } + + msg->addr = client->addr; + msg->flags = I2C_M_WR; + msg->len = 1; + msg->buf = data; + + data[0] = reg; + err = i2c_transfer(client->adapter, msg, 1); + dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d " + "flags=%d err=%d\n", + __func__, reg, data[1], msg->flags, err); + + if (err >= 0) { + mdelay(3); + msg->flags = I2C_M_RD; + msg->len = data_length; + err = i2c_transfer(client->adapter, msg, 1); + } + + if (err >= 0) { + *val = 0; + if (data_length == 1) + *val = data[0]; + else if (data_length == 2) + *val = data[1] + (data[0] << 8); + dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d " + "flags=%d err=%d\n", + __func__, reg, *val, msg->flags, err); + return 0; + } + + dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, " + "*val=%d flags=%d err=%d\n", + __func__, reg, *val, msg->flags, err); + return err; +} + +static int +sil9022_read_edid(struct i2c_client *client, u16 len, + char *p_buffer, u16 *out_len) +{ + int err = 0; + u8 val = 0; + int retries = 0; + int i = 0; + int k = 0; + + len = (len < HDMI_EDID_MAX_LENGTH) ? len : HDMI_EDID_MAX_LENGTH; + + /* Request DDC bus access to read EDID info from HDTV */ + dev_info(&client->dev, "<%s> Reading HDMI EDID\n", __func__); + + /* Bring transmitter to low-Power state */ + val = TPI_AVI_POWER_STATE_D2; + err = sil9022_write_reg(client, HDMI_TPI_DEVICE_POWER_STATE_DATA, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Failed during bring power state - low.\n", + __func__); + return err; + } + + /* Disable TMDS clock */ + val = 0x11; + err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Failed during bring power state - low.\n", + __func__); + return err; + } + + val = 0; + /* Read TPI system control register*/ + err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Reading DDC BUS REQUEST\n", __func__); + return err; + } + + /* The host writes 0x1A[2]=1 to request the + * DDC(Display Data Channel) bus + */ + val |= TPI_SYS_CTRL_DDC_BUS_REQUEST; + err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Writing DDC BUS REQUEST\n", __func__); + return err; + } + + /* Poll for bus DDC Bus control to be granted */ + dev_info(&client->dev, "<%s> Poll for DDC bus access\n", __func__); + val = 0; + do { + err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val); + if (retries++ > 100) + return err; + + } while ((val & TPI_SYS_CTRL_DDC_BUS_GRANTED) == 0); + + /* Close the switch to the DDC */ + val |= TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED; + err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Close switch to DDC BUS REQUEST\n", + __func__); + return err; + } + + memset(p_buffer, 0, len); + /* change I2C SetSlaveAddress to HDMI_I2C_MONITOR_ADDRESS */ + /* Read the EDID structure from the monitor I2C address */ + client->addr = HDMI_I2C_MONITOR_ADDRESS; + err = sil9022_blockread_reg(client, 1, len, + 0x00, p_buffer, out_len); + if (err < 0 || *out_len <= 0) { + dev_err(&client->dev, + "<%s> ERROR: Reading EDID from " + "HDMI_I2C_MONITOR_ADDRESS\n", __func__); + return err; + } + + for (i = 0; i < *out_len; i++) { + if ((i / 18) < 3) { + dev_dbg(&client->dev, "byte->%02x %x\n", + i, p_buffer[i]); + continue; + } + if ((i/18 >= 3 && i/18 <= 6) && (i%18 == 0)) + dev_dbg(&client->dev, "\n DTD Block %d\n", k++); + + if ((i/18 == 7) && (i%18 == 0)) + dev_dbg(&client->dev, "\n"); + + dev_dbg(&client->dev, "byte->%02x %x\n", i, p_buffer[i]); + } + + /* Release DDC bus access */ + client->addr = SI9022_I2CSLAVEADDRESS; + val &= ~(TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED); + err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val); + + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Releasing DDC Bus Access\n", + __func__); + return err; + } + + /* Success */ + return 0; +} + +static int +sil9022_enable_audio(struct i2c_client *client) +{ + int err = 0; + u8 val = 0; + u8 crc = 0; + u32 count = 0; + int index = 0; + + for (index = 0; + index < sizeof(hdmi_tpi_audio_config_data) / + sizeof(struct hdmi_reg_data); + index++) { + err = sil9022_write_reg( + client, + hdmi_tpi_audio_config_data[index].reg_offset, + hdmi_tpi_audio_config_data[index].value); + if (err != 0) { + dev_err(&client->dev, + "<%s> ERROR: Writing " + "tpi_audio_config_data[%d]={ %d, %d }\n", + __func__, index, + hdmi_tpi_audio_config_data[index].reg_offset, + hdmi_tpi_audio_config_data[index].value); + return err; + } + } + + /* Fill the checksum byte for Infoframe data*/ + count = 0; + while (count < MISC_INFOFRAME_SIZE_MEMORY) { + crc += misc_audio_info_frame_data[count]; + count++; + } + crc = 0x100 - crc; + + /* Fill CRC Byte*/ + misc_audio_info_frame_data[0x3] = crc; + + for (count = 0; count < MISC_INFOFRAME_SIZE_MEMORY; count++) { + err = sil9022_write_reg(client, + (HDMI_CPI_MISC_IF_OFFSET + count), + misc_audio_info_frame_data[count]); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: writing audio info frame" + " CRC data: %d\n", __func__, count); + return err; + } + } + + /* Decode Level 0 Packets */ + val = 0x2; + sil9022_write_reg(client, 0xBC, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: writing level 0 packets to 0xBC\n", + __func__); + return err; + } + + val = 0x24; + err = sil9022_write_reg(client, 0xBD, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: writing level 0 packets to 0xBD\n", + __func__); + return err; + } + + val = 0x2; + err = sil9022_write_reg(client, 0xBE, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: writing level 0 packets to 0xBE\n", + __func__); + return err; + } + + /* Disable Mute */ + val = TPI_AUDIO_INTERFACE_I2S | + TPI_AUDIO_MUTE_DISABLE | + TPI_AUDIO_CODING_PCM; + err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Disabling mute\n", + __func__); + return err; + } + + dev_info(&client->dev, "<%s> hdmi audio enabled\n", + __func__); + return 0; + +} + +static int +sil9022_disable_audio(struct i2c_client *client) +{ + u8 val = 0; + int err = 0; + /* Disable Audio */ + val = TPI_AUDIO_INTERFACE_DISABLE; + err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val); + if (err < 0) + dev_err(&client->dev, + "<%s> ERROR: Disisable audio interface", __func__); + + dev_info(&client->dev, "<%s> hdmi audio disabled\n", __func__); + return err; +} + +static int +sil9022_enable(struct omap_dss_device *dssdev) +{ + int err; + u8 val, vals[14]; + int i; + u16 out_len = 0; + u8 edid[HDMI_EDID_MAX_LENGTH]; + u16 horizontal_res; + u16 vertical_res; + u16 pixel_clk; + + memset(edid, 0, HDMI_EDID_MAX_LENGTH); + memset(vals, 0, 14); + + err = sil9022_read_edid(sil9022_client, HDMI_EDID_MAX_LENGTH, + edid, &out_len); + if (err < 0 || out_len == 0) { + dev_err(&sil9022_client->dev, + "<%s> Unable to read EDID for monitor\n", __func__); + return err; + } + + get_edid_timing_data(edid, + &pixel_clk, + &horizontal_res, + &vertical_res + ); + + /* Fill the TPI Video Mode Data structure */ + vals[0] = (pixel_clk & 0xFF); /* Pixel clock */ + vals[1] = ((pixel_clk & 0xFF00) >> 8); + vals[2] = VERTICAL_FREQ; /* Vertical freq */ + vals[3] = 0x00; + vals[4] = (horizontal_res & 0xFF); /* Horizontal pixels*/ + vals[5] = ((horizontal_res & 0xFF00) >> 8); + vals[6] = (vertical_res & 0xFF); /* Vertical pixels */ + vals[7] = ((vertical_res & 0xFF00) >> 8); + + dev_info(&sil9022_client->dev, "<%s>\nHDMI Monitor E-EDID Timing Data\n" + "horizontal_res = %d\n" + "vertical_res = %d\n" + "pixel_clk = %d\n" + "hfp = %d\n" + "hsw = %d\n" + "hbp = %d\n" + "vfp = %d\n" + "vsw = %d\n" + "vbp = %d\n", + __func__, + omap_dss_hdmi_timings.x_res, + omap_dss_hdmi_timings.y_res, + omap_dss_hdmi_timings.pixel_clock, + omap_dss_hdmi_timings.hfp, + omap_dss_hdmi_timings.hsw, + omap_dss_hdmi_timings.hbp, + omap_dss_hdmi_timings.vfp, + omap_dss_hdmi_timings.vsw, + omap_dss_hdmi_timings.vbp + ); + + dssdev->panel.timings = omap_dss_hdmi_timings; + /* Write out the TPI Video Mode Data */ + out_len = 0; + err = sil9022_blockwrite_reg(sil9022_client, + HDMI_TPI_VIDEO_DATA_BASE_REG, + 8, vals, &out_len); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: writing TPI video mode data\n", __func__); + return err; + } + + /* Write out the TPI Pixel Repetition Data (24 bit wide bus, + falling edge, no pixel replication) */ + val = TPI_AVI_PIXEL_REP_BUS_24BIT | + TPI_AVI_PIXEL_REP_FALLING_EDGE | + TPI_AVI_PIXEL_REP_NONE; + err = sil9022_write_reg(sil9022_client, + HDMI_TPI_PIXEL_REPETITION_REG, + val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: writing TPI pixel repetition data\n", + __func__); + return err; + } + + /* Write out the TPI AVI Input Format */ + val = TPI_AVI_INPUT_BITMODE_8BIT | + TPI_AVI_INPUT_RANGE_AUTO | + TPI_AVI_INPUT_COLORSPACE_RGB; + err = sil9022_write_reg(sil9022_client, + HDMI_TPI_AVI_IN_FORMAT_REG, + val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: writing TPI AVI Input format\n", __func__); + return err; + } + + /* Write out the TPI AVI Output Format */ + val = TPI_AVI_OUTPUT_CONV_BT709 | + TPI_AVI_OUTPUT_RANGE_AUTO | + TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI; + err = sil9022_write_reg(sil9022_client, + HDMI_TPI_AVI_OUT_FORMAT_REG, val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: writing TPI AVI output format\n", + __func__); + return err; + } + + /* Write out the TPI System Control Data to power down */ + val = TPI_SYS_CTRL_POWER_DOWN; + err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: writing TPI power down control data\n", + __func__); + return err; + } + + /* Write out the TPI AVI InfoFrame Data (all defaults) */ + /* Compute CRC*/ + val = 0x82 + 0x02 + 13; + + for (i = 0; i < sizeof(avi_info_frame_data); i++) + val += avi_info_frame_data[i]; + + avi_info_frame_data[0] = 0x100 - val; + + out_len = 0; + err = sil9022_blockwrite_reg(sil9022_client, + HDMI_TPI_AVI_DBYTE_BASE_REG, + sizeof(avi_info_frame_data), + avi_info_frame_data, &out_len); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: writing TPI AVI infoframe data\n", + __func__); + return err; + } + + /* Audio Configuration */ + err = sil9022_enable_audio(sil9022_client); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: Unable set audio configuration\n", + __func__); + return err; + } + + /* Write out the TPI Device Power State (D0) */ + val = TPI_AVI_POWER_STATE_D0; + err = sil9022_write_reg(sil9022_client, + HDMI_TPI_POWER_STATE_CTRL_REG, val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: Setting device power state to D0\n", + __func__); + return err; + } + + /* Write out the TPI System Control Data to power up and + * select output mode + */ + val = TPI_SYS_CTRL_POWER_ACTIVE | TPI_SYS_CTRL_OUTPUT_MODE_HDMI; + err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: Writing system control data\n", __func__); + return err; + } + + /* Read back TPI System Control Data to latch settings */ + msleep(20); + err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: Writing system control data\n", + __func__); + return err; + } + + /* HDCP Enable - Disable */ + val = 0; + err = sil9022_write_reg(sil9022_client, + HDMI_TPI_HDCP_CONTROLDATA_REG, val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: Enable (1) / Disable (0) => HDCP: %d\n", + __func__, val); + return err; + } + + dev_info(&sil9022_client->dev, "<%s> hdmi enabled\n", __func__); + return 0; + +} + +static int +sil9022_disable(void) +{ + u8 val = 0; + int err = 0; + + err = sil9022_disable_audio(sil9022_client); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: failed to disable audio\n", __func__); + return err; + } + + /* Write out the TPI System Control Data to power down */ + val = TPI_SYS_CTRL_POWER_DOWN; + err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: writing control data - power down\n", + __func__); + return err; + } + + /* Write out the TPI Device Power State (D2) */ + val = TPI_AVI_POWER_STATE_D2; + err = sil9022_write_reg(sil9022_client, + HDMI_TPI_DEVICE_POWER_STATE_DATA, val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: Setting device power state to D2\n", + __func__); + return err; + } + + /* Read back TPI System Control Data to latch settings */ + mdelay(10); + err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val); + if (err < 0) { + dev_err(&sil9022_client->dev, + "<%s> ERROR: Reading System control data " + "- latch settings\n", __func__); + return err; + } + + dev_info(&sil9022_client->dev, "<%s> hdmi disabled\n", __func__); + return 0; + +} + +static int sil9022_set_reg_read_ctrl(struct i2c_client *client) +{ + int err = 0; + u8 ver; + + /* probe for sil9022 chip version*/ + err = sil9022_write_reg(client, SI9022_REG_TPI_RQB, 0x00); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Writing HDMI configuration to " + "reg - SI9022_REG_TPI_RQB\n", __func__); + err = -ENODEV; + goto ERROR1; + } + + err = sil9022_read_reg(client, 1, SI9022_REG_CHIPID0, &ver); + if (err < 0) { + dev_err(&client->dev, + "<%s> ERROR: Reading HDMI version Id\n", __func__); + err = -ENODEV; + goto ERROR1; + } else if (ver != SI9022_CHIPID_902x) { + dev_err(&client->dev, + "<%s> Not a valid verId: 0x%x\n", __func__, ver); + err = -ENODEV; + goto ERROR1; + } else + dev_info(&client->dev, + "<%s> sil9022 HDMI Chip version = %x\n", + __func__, ver); + + return 0; +ERROR1: + return err; +} + +static inline struct sil9022_platform_data +*get_panel_data(const struct omap_dss_device *dssdev) +{ + return (struct sil9022_platform_data *) dssdev->data; +} + + +static int sil9022_panel_probe(struct omap_dss_device *dssdev) +{ + struct sil9022_platform_data *sidata = get_panel_data(dssdev); + int r; + if (!sidata) + return -EINVAL; + + dssdev->panel.timings = omap_dss_hdmi_timings; + + if (gpio_is_valid(sidata->res_gpio)) { + r = devm_gpio_request_one(&dssdev->dev, sidata->res_gpio, + GPIOF_OUT_INIT_HIGH, "HDMI"); + if (r) + return r; + } + + return 0; +} + +static void sil9022_panel_remove(struct omap_dss_device *dssdev) +{ + omap_dss_unregister_driver(dssdev->driver); +} + + +static int sil9022_panel_power_on(struct omap_dss_device *dssdev) +{ + int r = 0; + struct sil9022_platform_data *sidata = get_panel_data(dssdev); + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + return 0; + + if (gpio_is_valid(sidata->res_gpio)) + gpio_set_value_cansleep(sidata->res_gpio, 1); + + omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings); + omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines); + r = omapdss_dpi_display_enable(dssdev); + return r; + +} + +static void sil9022_panel_power_off(struct omap_dss_device *dssdev) +{ + struct sil9022_platform_data *sidata = get_panel_data(dssdev); + + if (gpio_is_valid(sidata->res_gpio)) + gpio_set_value_cansleep(sidata->res_gpio, 0); + return; + +} + +static int sil9022_panel_enable(struct omap_dss_device *dssdev) +{ + int r = 0; + + r = sil9022_panel_power_on(dssdev); + if (r) + goto ERROR0; + r = sil9022_set_reg_read_ctrl(sil9022_client); + if (r) + goto ERROR0; + + r = sil9022_enable(dssdev); + if (r) + goto ERROR0; + /* wait couple of vsyncs until enabling the LCD */ + msleep(50); + return 0; + +ERROR0: + return r; +} + +static void sil9022_panel_disable(struct omap_dss_device *dssdev) +{ + sil9022_disable(); + /* wait couple of vsyncs until enabling the hdmi */ + msleep(50); + sil9022_panel_power_off(dssdev); + return; +} + +static struct omap_dss_driver hdmi_driver = { + .probe = sil9022_panel_probe, + .remove = sil9022_panel_remove, + + .enable = sil9022_panel_enable, + .disable = sil9022_panel_disable, + + .driver = { + .name = "sil9022_panel", + .owner = THIS_MODULE, + }, +}; + +static int +sil9022_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int err = 0; + + sil9022_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!sil9022_client) { + err = -ENOMEM; + goto ERROR0; + } + memset(sil9022_client, 0, sizeof(struct i2c_client)); + + strncpy(sil9022_client->name, client->name, I2C_NAME_SIZE); + sil9022_client->addr = client->addr; + sil9022_client->adapter = client->adapter; + + err = sil9022_set_reg_read_ctrl(client); + if (err) + goto ERROR1; + + omap_dss_register_driver(&hdmi_driver); + return 0; + +ERROR1: + kfree(sil9022_client); +ERROR0: + return err; +} + + +static int +sil9022_remove(struct i2c_client *client) + +{ + int err = 0; + + if (!client->adapter) { + dev_err(&sil9022_client->dev, "<%s> No HDMI Device\n", + __func__); + return -ENODEV; + } + kfree(sil9022_client); + + return err; +} + +static const struct i2c_device_id sil9022_id[] = { + { SIL9022_DRV_NAME, 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, sil9022_id); + +static struct i2c_driver sil9022_driver = { + .driver = { + .name = SIL9022_DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = sil9022_probe, + .remove = sil9022_remove, + .id_table = sil9022_id, +}; + +static int __init +sil9022_init(void) +{ + int err = 0; + err = i2c_add_driver(&sil9022_driver); + if (err < 0) { + printk(KERN_ERR "<%s> Driver registration failed\n", __func__); + err = -ENODEV; + goto ERROR0; + } + + if (sil9022_client == NULL) { + printk(KERN_ERR "<%s> sil9022_client not allocated\n" + "<%s> No HDMI Device\n", __func__, __func__); + err = -ENODEV; + goto ERROR0; + } + return 0; + +ERROR0: + return err; +} + +static void __exit +sil9022_exit(void) +{ + i2c_del_driver(&sil9022_driver); +} + +late_initcall(sil9022_init); +module_exit(sil9022_exit); + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("SIL9022 HDMI Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/displays/panel-sil9022.h b/drivers/video/omap2/displays/panel-sil9022.h new file mode 100644 index 0000000..7c920c0 --- /dev/null +++ b/drivers/video/omap2/displays/panel-sil9022.h @@ -0,0 +1,527 @@ +/* + * drivers/video/omap2/displays/panel-sil9022.c + * + * Copyright (C) 2009 Texas Instruments + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + * sil9022 hdmi driver + */ +#ifndef _SI9022_H_ +#define _SI9022_H_ + +#define SIL9022_DRV_NAME "sil9022" + +#define CLKOUT2_EN (0x1 << 7) +#define CLKOUT2_DIV (0x4 << 3) +#define CLKOUT2SOURCE (0x2 << 0) +#define CM_CLKOUT_CTRL 0x48004D70 + +#define HDMI_XRES 1280 +#define HDMI_YRES 720 +#define HDMI_PIXCLOCK_MAX 74250 +#define VERTICAL_FREQ 0x3C + +#define I2C_M_WR 0 + +#define SI9022_USERST_PIN 1 + +#define SI9022_REG_PIX_CLK_LSB 0x00 +#define SI9022_REG_PIX_CLK_MSB 0x01 + +#define SI9022_REG_PIX_REPETITION 0x08 +#define SI9022_REG_INPUT_FORMAT 0x09 +#define SI9022_REG_OUTPUT_FORMAT 0x0A +#define SI9022_REG_SYNC_GEN_CTRL 0x60 + +#define SI9022_REG_DE_CTRL 0x63 +#define DE_DLY_MSB_BITPOS 0 +#define HSYNCPOL_INVERT_BITPOS 4 +#define VSYNCPOL_INVERT_BITPOS 5 +#define DE_GENERATOR_EN_BITPOS 6 + +#define SI9022_REG_PWR_STATE 0x1E + +#define SI9022_REG_TPI_RQB 0xC7 + +#define SI9022_REG_INT_PAGE 0xBC +#define SI9022_REG_OFFSET 0xBD +#define SI9022_REG_VALUE 0xBE + +#define SI9022_PLLMULT_BITPOS 0x05 + +#define SI9022_REG_TPI_SYSCTRL 0x1A +#define I2DDCREQ_BITPOS 2 +#define TMDS_ENABLE_BITPOS 4 +#define HDMI_ENABLE_BITPOS 0 + +#define SI9022_REG_CHIPID0 0x1B +#define SI9022_REG_CHIPID1 0x1C +#define SI9022_REG_CHIPID2 0x1D +#define SI9022_REG_HDCPVER 0x30 + +#define SI9022_REG_INTSTATUS 0x3D +#define HOTPLUG_PENDING_BITPOS 0 +#define RCV_SENSE_PENDING_BITPOS 1 +#define HOTPLUG_SENSE_BITPOS 2 +#define RX_SENSE_BITPOS 3 +#define AUDIO_ERR_PENDING_BITPOS 4 + + +#define SI9022_I2CSLAVEADDRESS 0x39 + +#define SI9022_CHIPID_902x 0xB0 + +#define SI9022_MAXRETRY 100 + +#define SI9022_EDID_DETAILED_TIMING_OFFSET 0x36 /*EDID Detailed Timing */ + /*Info 0 begin offset*/ +#define SI9022_EDID_PIX_CLK_OFFSET 0 +#define SI9022_EDID_H_ACTIVE_OFFSET 2 +#define SI9022_EDID_H_BLANKING_OFFSET 3 +#define SI9022_EDID_V_ACTIVE_OFFSET 5 +#define SI9022_EDID_V_BLANKING_OFFSET 6 +#define SI9022_EDID_H_SYNC_OFFSET 8 +#define SI9022_EDID_H_SYNC_PW_OFFSET 9 +#define SI9022_EDID_V_SYNC_OFFSET 10 +#define SI9022_EDID_V_SYNC_PW_OFFSET 10 +#define SI9022_EDID_H_IMAGE_SIZE_OFFSET 12 +#define SI9022_EDID_V_IMAGE_SIZE_OFFSET 13 +#define SI9022_EDID_H_BORDER_OFFSET 15 +#define SI9022_EDID_V_BORDER_OFFSET 16 +#define SI9022_EDID_FLAGS_OFFSET 17 + +#define SI9022_PLUG_DETECTED 0xF0 +#define SI9022_UNPLUG_DETECTED 0xF1 + + +/* --------------------------------------------------------------------- */ +#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 + +/* HDMI Connected States */ +#define HDMI_STATE_NOMONITOR 0 /* NOT CONNECTED */ +#define HDMI_STATE_CONNECTED 1 /* CONNECTED */ +#define HDMI_STATE_ON 2 /* CONNECTED AND POWERED ON */ + + +/* HDMI EDID Length */ +#define HDMI_EDID_MAX_LENGTH 256 + +/* HDMI EDID DTDs */ +#define HDMI_EDID_MAX_DTDS 4 + +/* HDMI EDID DTD Tags */ +#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC +#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF +#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD + + +/* HDMI EDID Extension Data Block Tags */ +#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0 +#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F + +#define HDMI_EDID_EX_DATABLOCK_AUDIO 0x20 +#define HDMI_EDID_EX_DATABLOCK_VIDEO 0x40 +#define HDMI_EDID_EX_DATABLOCK_VENDOR 0x60 +#define HDMI_EDID_EX_DATABLOCK_SPEAKERS 0x80 + +/* HDMI EDID Extenion Data Block Values: Video */ +#define HDMI_EDID_EX_VIDEO_NATIVE 0x80 +#define HDMI_EDID_EX_VIDEO_MASK 0x7F +#define HDMI_EDID_EX_VIDEO_MAX 35 + +#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3 1 +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3 2 +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9 3 +#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9 4 +#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9 5 +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3 6 +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9 7 +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3 8 +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9 9 +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3 10 +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9 11 +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3 12 +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9 13 +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3 14 +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9 15 +#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9 16 +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3 17 +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9 18 +#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9 19 +#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9 20 +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3 21 +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9 22 +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3 23 +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9 24 +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3 25 +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9 26 +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3 27 +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9 28 +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3 29 +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9 30 +#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9 31 +#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9 32 +#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9 33 +#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9 34 + +/* HDMI TPI Registers */ +#define HDMI_TPI_VIDEO_DATA_BASE_REG 0x00 +#define HDMI_TPI_PIXEL_CLK_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x00) +#define HDMI_TPI_PIXEL_CLK_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x01) +#define HDMI_TPI_VFREQ_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x02) +#define HDMI_TPI_VFREQ_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x03) +#define HDMI_TPI_PIXELS_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x04) +#define HDMI_TPI_PIXELS_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x05) +#define HDMI_TPI_LINES_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x06) +#define HDMI_TPI_LINES_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x07) + +#define HDMI_TPI_PIXEL_REPETITION_REG 0x08 + +#define HDMI_TPI_AVI_INOUT_BASE_REG 0x09 +#define HDMI_TPI_AVI_IN_FORMAT_REG (HDMI_TPI_AVI_INOUT_BASE_REG + 0x00) +#define HDMI_TPI_AVI_OUT_FORMAT_REG (HDMI_TPI_AVI_INOUT_BASE_REG + 0x01) + +#define HDMI_SYS_CTRL_DATA_REG 0x1A + +#define HDMI_TPI_SYN_GENERATOR_REG 0x60 + +#define HDMI_TPI_VIDEO_SYN_POLARITY_REG 0x61 + +#define HDMI_TPI_DE_BASE_REG 0x62 +#define HDMI_TPI_DE_DLY_LSB_REG (HDMI_TPI_DE_BASE_REG + 0x0) +#define HDMI_TPI_DE_DLY_MSB_REG (HDMI_TPI_DE_BASE_REG + 0x1) +#define HDMI_TPI_DE_TOP_REG (HDMI_TPI_DE_BASE_REG + 0x2) +#define HDMI_TPI_DE_RSVD_REG (HDMI_TPI_DE_BASE_REG + 0x3) +#define HDMI_TPI_DE_CNT_LSB_REG (HDMI_TPI_DE_BASE_REG + 0x4) +#define HDMI_TPI_DE_CNT_MSB_REG (HDMI_TPI_DE_BASE_REG + 0x5) +#define HDMI_TPI_DE_LIN_LSB_REG (HDMI_TPI_DE_BASE_REG + 0x6) +#define HDMI_TPI_DE_LIN_MSB_REG (HDMI_TPI_DE_BASE_REG + 0x7) + +#define HDMI_TPI_HRES_LSB_REG 0x6A +#define HDMI_TPI_HRES_MSB_REG 0x6B + +#define HDMI_TPI_VRES_LSB_REG 0x6C +#define HDMI_TPI_VRES_MSB_REG 0x6D + +#define HDMI_TPI_RQB_REG 0xC7 +#define HDMI_TPI_DEVID_REG 0x1B +#define HDMI_TPI_DEVREV_REG 0x1C + +#define HDMI_TPI_DEVICE_POWER_STATE_DATA 0x1E +#define HDMI_REQ_GRANT_BMODE_REG 0xC7 +#define HDMI_TPI_DEVICE_ID_REG 0x1B +#define HDMI_TPI_REVISION_REG 0x1C +#define HDMI_TPI_ID_BYTE2_REG 0x1D +#define HDMI_TPI_POWER_STATE_CTRL_REG 0x1E + +#define HDMI_TPI_INTERRUPT_ENABLE_REG 0x3C +#define HDMI_TPI_INTERRUPT_STATUS_REG 0x3D + + +/* AVI InfoFrames can be readed byte by byte but must be write in a burst */ +#define HDMI_TPI_AVI_DBYTE_BASE_REG 0x0C +#define HDMI_TPI_AVI_DBYTE0_CHKSUM_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x00) +#define HDMI_TPI_AVI_DBYTE1_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x01) +#define HDMI_TPI_AVI_DBYTE2_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x02) +#define HDMI_TPI_AVI_DBYTE3_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x03) +#define HDMI_TPI_AVI_DBYTE4_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x04) +#define HDMI_TPI_AVI_DBYTE5_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x05) +#define HDMI_TPI_AVI_ETB_LSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x06) +#define HDMI_TPI_AVI_ETB_MSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x07) +#define HDMI_TPI_AVI_SBB_LSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x08) +#define HDMI_TPI_AVI_SBB_MSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x09) +#define HDMI_TPI_AVI_ELB_LSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x0A) +#define HDMI_TPI_AVI_ELB_MSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x0B) +#define HDMI_TPI_AVI_SRB_LSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x0C) +#define HDMI_TPI_AVI_SRB_MSB_REG (HDMI_TPI_AVI_DBYTE_BASE_REG + 0x0D) + +#define HDMI_CPI_MISC_IF_SELECT_REG 0xBF +#define HDMI_CPI_MISC_IF_OFFSET 0xC0 + +#define MISC_INFOFRAME_SIZE_MEMORY 14 +#define MISC_INFOFRAME_TYPE_SUBOFFSET 0 +#define MISC_INFOFRAME_VERSION_SUBOFFSET 1 +#define MISC_INFOFRAME_LENGTH_SUBOFFSET 2 +#define MISC_INFOFRAME_CHECKSUM_SUBOFFSET 3 +#define MISC_INFOFRAME_DBYTE1_SUBOFFSET 4 +#define MISC_INFOFRAME_DBYTE2_SUBOFFSET 5 +#define MISC_INFOFRAME_DBYTE3_SUBOFFSET 6 +#define MISC_INFOFRAME_DBYTE4_SUBOFFSET 7 +#define MISC_INFOFRAME_DBYTE5_SUBOFFSET 8 +#define MISC_INFOFRAME_DBYTE6_SUBOFFSET 9 +#define MISC_INFOFRAME_DBYTE7_SUBOFFSET 10 +#define MISC_INFOFRAME_DBYTE8_SUBOFFSET 11 +#define MISC_INFOFRAME_DBYTE9_SUBOFFSET 12 +#define MISC_INFOFRAME_DBYTE10_SUBOFFSET 13 + +#define HDMI_CPI_MISC_TYPE_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_TYPE_SUBOFFSET) +#define HDMI_CPI_MISC_VERSION_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_VERSION_SUBOFFSET) +#define HDMI_CPI_MISC_LENGTH_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_LENGTH_SUBOFFSET) +#define HDMI_CPI_MISC_CHECKSUM_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_CHECKSUM_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE1_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE1_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE2_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE2_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE3_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE3_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE4_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE4_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE5_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE5_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE6_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE6_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE7_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE7_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE8_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE8_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE9_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE9_SUBOFFSET) +#define HDMI_CPI_MISC_DBYTE10_REG (HDMI_CPI_MISC_IF_OFFSET\ + + MISC_INFOFRAME_DBYTE10_SUBOFFSET) + +/* Audio */ +#define HDMI_TPI_I2S_ENABLE_MAPPING_REG 0x1F +#define HDMI_TPI_I2S_INPUT_CONFIG_REG 0x20 +#define HDMI_TPI_I2S_STRM_HDR_BASE 0x21 +#define HDMI_TPI_I2S_STRM_HDR_0_REG (HDMI_TPI_I2S_STRM_HDR_BASE + 0) +#define HDMI_TPI_I2S_STRM_HDR_1_REG (HDMI_TPI_I2S_STRM_HDR_BASE + 1) +#define HDMI_TPI_I2S_STRM_HDR_2_REG (HDMI_TPI_I2S_STRM_HDR_BASE + 2) +#define HDMI_TPI_I2S_STRM_HDR_3_REG (HDMI_TPI_I2S_STRM_HDR_BASE + 3) +#define HDMI_TPI_I2S_STRM_HDR_4_REG (HDMI_TPI_I2S_STRM_HDR_BASE + 4) +#define HDMI_TPI_AUDIO_CONFIG_BYTE2_REG 0x26 +#define HDMI_TPI_AUDIO_CONFIG_BYTE3_REG 0x27 +#define HDMI_TPI_AUDIO_CONFIG_BYTE4_REG 0x28 + +/* HDCP */ +#define HDMI_TPI_HDCP_QUERYDATA_REG 0x29 +#define HDMI_TPI_HDCP_CONTROLDATA_REG 0x2A + +/* HDMI_TPI_DEVICE_ID_REG */ +#define TPI_DEVICE_ID 0xB0 + +/* HDMI_TPI_REVISION_REG */ +#define TPI_REVISION 0x00 + +/* HDMI_TPI_ID_BYTE2_REG */ +#define TPI_ID_BYTE2_VALUE 0x00 + +/* HDMI_SYS_CTRL_DATA_REG */ +#define TPI_SYS_CTRL_POWER_DOWN (1 << 4) +#define TPI_SYS_CTRL_POWER_ACTIVE (0 << 4) +#define TPI_SYS_CTRL_AV_MUTE (1 << 3) +#define TPI_SYS_CTRL_DDC_BUS_REQUEST (1 << 2) +#define TPI_SYS_CTRL_DDC_BUS_GRANTED (1 << 1) +#define TPI_SYS_CTRL_OUTPUT_MODE_HDMI (1 << 0) +#define TPI_SYS_CTRL_OUTPUT_MODE_DVI (0 << 0) + + +/* HDMI Monitor I2C default address */ +#define HDMI_I2C_MONITOR_ADDRESS 0x50 + + +/* HDMI_TPI_INTR_ENABLE */ +#define TPI_INTR_ENABLE_SECURITY_EVENT (1 << 5) +#define TPI_INTR_ENABLE_AUDIO_EVENT (1 << 4) +#define TPI_INTR_ENABLE_CPI_EVENT (1 << 3) +#define TPI_INTR_ENABLE_RECEIVER_EVENT (1 << 1) +#define TPI_INTR_ENABLE_HOTPLUG_EVENT (1 << 0) + +/* HDMI_TPI_INTR_STATUS */ +#define TPI_INTR_STATUS_SECURITY_EVENT (1 << 5) +#define TPI_INTR_STATUS_AUDIO_EVENT (1 << 4) +#define TPI_INTR_STATUS_POWERED_EVENT (1 << 3) +#define TPI_INTR_STATUS_HOTPLUG_STATE (1 << 2) +#define TPI_INTR_STATUS_RECEIVER_EVENT (1 << 1) +#define TPI_INTR_STATUS_HOTPLUG_EVENT (1 << 0) + + +/* HDMI_TPI_PIXEL_REPETITION */ +#define TPI_AVI_PIXEL_REP_BUS_24BIT (1 << 5) +#define TPI_AVI_PIXEL_REP_BUS_12BIT (0 << 5) +#define TPI_AVI_PIXEL_REP_RISING_EDGE (1 << 4) +#define TPI_AVI_PIXEL_REP_FALLING_EDGE (0 << 4) +#define TPI_AVI_PIXEL_REP_4X (3 << 0) +#define TPI_AVI_PIXEL_REP_2X (1 << 0) +#define TPI_AVI_PIXEL_REP_NONE (0 << 0) + +/* HDMI_TPI_AVI_INPUT_FORMAT */ +#define TPI_AVI_INPUT_BITMODE_12BIT (1 << 7) +#define TPI_AVI_INPUT_BITMODE_8BIT (0 << 7) +#define TPI_AVI_INPUT_DITHER (1 << 6) +#define TPI_AVI_INPUT_RANGE_LIMITED (2 << 2) +#define TPI_AVI_INPUT_RANGE_FULL (1 << 2) +#define TPI_AVI_INPUT_RANGE_AUTO (0 << 2) +#define TPI_AVI_INPUT_COLORSPACE_BLACK (3 << 0) +#define TPI_AVI_INPUT_COLORSPACE_YUV422 (2 << 0) +#define TPI_AVI_INPUT_COLORSPACE_YUV444 (1 << 0) +#define TPI_AVI_INPUT_COLORSPACE_RGB (0 << 0) + + +/* HDMI_TPI_AVI_OUTPUT_FORMAT */ +#define TPI_AVI_OUTPUT_CONV_BT709 (1 << 4) +#define TPI_AVI_OUTPUT_CONV_BT601 (0 << 4) +#define TPI_AVI_OUTPUT_RANGE_LIMITED (2 << 2) +#define TPI_AVI_OUTPUT_RANGE_FULL (1 << 2) +#define TPI_AVI_OUTPUT_RANGE_AUTO (0 << 2) +#define TPI_AVI_OUTPUT_COLORSPACE_RGBDVI (3 << 0) +#define TPI_AVI_OUTPUT_COLORSPACE_YUV422 (2 << 0) +#define TPI_AVI_OUTPUT_COLORSPACE_YUV444 (1 << 0) +#define TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI (0 << 0) + + +/* HDMI_TPI_DEVICE_POWER_STATE */ +#define TPI_AVI_POWER_STATE_D3 (3 << 0) +#define TPI_AVI_POWER_STATE_D2 (2 << 0) +#define TPI_AVI_POWER_STATE_D0 (0 << 0) + +/* HDMI_TPI_AUDIO_CONFIG_BYTE2_REG */ +#define TPI_AUDIO_CODING_STREAM_HEADER (0 << 0) +#define TPI_AUDIO_CODING_PCM (1 << 0) +#define TPI_AUDIO_CODING_AC3 (2 << 0) +#define TPI_AUDIO_CODING_MPEG1 (3 << 0) +#define TPI_AUDIO_CODING_MP3 (4 << 0) +#define TPI_AUDIO_CODING_MPEG2 (5 << 0) +#define TPI_AUDIO_CODING_AAC (6 << 0) +#define TPI_AUDIO_CODING_DTS (7 << 0) +#define TPI_AUDIO_CODING_ATRAC (8 << 0) +#define TPI_AUDIO_MUTE_DISABLE (0 << 4) +#define TPI_AUDIO_MUTE_ENABLE (1 << 4) +#define TPI_AUDIO_INTERFACE_DISABLE (0 << 6) +#define TPI_AUDIO_INTERFACE_SPDIF (1 << 6) +#define TPI_AUDIO_INTERFACE_I2S (2 << 6) + +/* HDMI_TPI_AUDIO_CONFIG_BYTE3_REG */ +#define TPI_AUDIO_CHANNEL_STREAM (0 << 0) +#define TPI_AUDIO_2_CHANNEL (1 << 0) +#define TPI_AUDIO_8_CHANNEL (7 << 0) +#define TPI_AUDIO_FREQ_STREAM (0 << 3) +#define TPI_AUDIO_FREQ_32KHZ (1 << 3) +#define TPI_AUDIO_FREQ_44KHZ (2 << 3) +#define TPI_AUDIO_FREQ_48KHZ (3 << 3) +#define TPI_AUDIO_FREQ_88KHZ (4 << 3) +#define TPI_AUDIO_FREQ_96KHZ (5 << 3) +#define TPI_AUDIO_FREQ_176KHZ (6 << 3) +#define TPI_AUDIO_FREQ_192KHZ (7 << 3) +#define TPI_AUDIO_SAMPLE_SIZE_STREAM (0 << 6) +#define TPI_AUDIO_SAMPLE_SIZE_16 (1 << 6) +#define TPI_AUDIO_SAMPLE_SIZE_20 (2 << 6) +#define TPI_AUDIO_SAMPLE_SIZE_24 (3 << 6) + +/* HDMI_TPI_I2S_ENABLE_MAPPING_REG */ +#define TPI_I2S_SD_CONFIG_SELECT_SD0 (0 << 0) +#define TPI_I2S_SD_CONFIG_SELECT_SD1 (1 << 0) +#define TPI_I2S_SD_CONFIG_SELECT_SD2 (2 << 0) +#define TPI_I2S_SD_CONFIG_SELECT_SD3 (3 << 0) +#define TPI_I2S_LF_RT_SWAP_NO (0 << 2) +#define TPI_I2S_LF_RT_SWAP_YES (1 << 2) +#define TPI_I2S_DOWNSAMPLE_DISABLE (0 << 3) +#define TPI_I2S_DOWNSAMPLE_ENABLE (1 << 3) +#define TPI_I2S_SD_FIFO_0 (0 << 4) +#define TPI_I2S_SD_FIFO_1 (1 << 4) +#define TPI_I2S_SD_FIFO_2 (2 << 4) +#define TPI_I2S_SD_FIFO_3 (3 << 4) +#define TPI_I2S_SD_CHANNEL_DISABLE (0 << 7) +#define TPI_I2S_SD_CHANNEL_ENABLE (1 << 7) + + +/* HDMI_TPI_I2S_INPUT_CONFIG_REG */ +#define TPI_I2S_FIRST_BIT_SHIFT_YES (0 << 0) +#define TPI_I2S_FIRST_BIT_SHIFT_NO (1 << 0) +#define TPI_I2S_SD_DIRECTION_MSB_FIRST (0 << 1) +#define TPI_I2S_SD_DIRECTION_LSB_FIRST (1 << 1) +#define TPI_I2S_SD_JUSTIFY_LEFT (0 << 2) +#define TPI_I2S_SD_JUSTIFY_RIGHT (1 << 2) +#define TPI_I2S_WS_POLARITY_LOW (0 << 3) +#define TPI_I2S_WS_POLARITY_HIGH (1 << 3) +#define TPI_I2S_MCLK_MULTIPLIER_128 (0 << 4) +#define TPI_I2S_MCLK_MULTIPLIER_256 (1 << 4) +#define TPI_I2S_MCLK_MULTIPLIER_384 (2 << 4) +#define TPI_I2S_MCLK_MULTIPLIER_512 (3 << 4) +#define TPI_I2S_MCLK_MULTIPLIER_768 (4 << 4) +#define TPI_I2S_MCLK_MULTIPLIER_1024 (5 << 4) +#define TPI_I2S_MCLK_MULTIPLIER_1152 (6 << 4) +#define TPI_I2S_MCLK_MULTIPLIER_192 (7 << 4) +#define TPI_I2S_SCK_EDGE_FALLING (0 << 7) +#define TPI_I2S_SCK_EDGE_RISING (1 << 7) + +/* HDMI_TPI_I2S_STRM_HDR_REG */ +/* the reference of this values is in IEC 60958-3 */ +#define I2S_CHAN_STATUS_MODE 0x00 +#define I2S_CHAN_STATUS_CAT_CODE 0x00 +#define I2S_CHAN_SOURCE_CHANNEL_NUM 0x00 +#define I2S_CHAN_ACCURACY_N_44_SAMPLING_FS 0x20 +#define I2S_CHAN_ACCURACY_N_48_SAMPLING_FS 0x22 +#define I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH 0xD2 + + +/* MISCELLANOUS INFOFRAME VALUES */ + +#define HDMI_INFOFRAME_TX_ENABLE (0x1 << 7) +#define HDMI_INFOFRAME_TX_REPEAT (0x1 << 6) +#define HDMI_AUDIO_INFOFRAME (0x2 << 0) + +/* Stream Header Data */ +#define HDMI_SH_PCM (0x1 << 4) +#define HDMI_SH_TWO_CHANNELS (0x1 << 0) +#define HDMI_SH_44KHz (0x2 << 2) +#define HDMI_SH_48KHz (0x3 << 2) +#define HDMI_SH_16BIT (0x1 << 0) +#define HDMI_SH_SPKR_FLFR 0x0 +#define HDMI_SH_0dB_ATUN 0x0 + +/* MISC_TYPE */ +#define MISC_INFOFRAME_TYPE 0x04 /* for Audio */ +#define MISC_INFOFRAME_ALWAYS_SET 0x80 + +/* MISC_VERSION */ +#define MISC_INFOFRAME_VERSION 0x01 + +/* MISC_LENGTH */ +#define MISC_INFOFRAME_LENGTH 0x0A /*length for Audio infoframe*/ +#define MISC_INFOFRAME_LENGTH_RSVD_BITS 0xE0 + +/* MISC_DBYTE1 */ +/* Type, Encoding, Trandport */ +#define MISC_DBYTE1_CT_CHK_HEADER_STREAM 0x00 + +/* audio channel count */ +#define MISC_DBYTE1_CC_CHK_HEADER_STREAM 0x00 +#define MISC_DBYTE1_CC_2_CHANNELS 0x01 + +/* MISC_DBYTE2 */ +/*Sample Size */ +#define MISC_DBYTE2_SS_CHK_HEADER_STREAM 0x00 /* for hdmi by default */ + +/* Sampling Frequency */ +#define MISC_DBYTE2_SF_CHK_HEADER_STREAM 0x00 /* for hdmi by default */ + +/* MISC_DBYTE3 */ +/* Code Extention */ +#define MISC_DBYTE3_CTX_TAKE_DBYTE1 0x00 /* for hdmi by default */ + +/* MISC_DBYTE4 */ +#define MISC_DBYTE4 0x00 /*for no multichannel( */ + /* multichannel means more*/ + /* than 2 channels */ + +/* MISC_DBYTE5 */ +#define MISC_DBYTE5 0x00 /* for no multichannel(multichannel */ + /* means more than 2 channels */ + +struct hdmi_reg_data { + u8 reg_offset; + u8 value; +}; + +#endif -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html