aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c')
-rw-r--r--drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c805
1 files changed, 0 insertions, 805 deletions
diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
deleted file mode 100644
index e5bdd99ad453..000000000000
--- a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * Copyright © 2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/gpio/consumer.h>
-
-#include <asm/intel_scu_ipc.h>
-
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_pkg_sender.h"
-#include "mdfld_output.h"
-#include "tc35876x-dsi-lvds.h"
-
-static struct i2c_client *tc35876x_client;
-static struct i2c_client *cmi_lcd_i2c_client;
-/* Panel GPIOs */
-static struct gpio_desc *bridge_reset;
-static struct gpio_desc *bridge_bl_enable;
-static struct gpio_desc *backlight_voltage;
-
-
-#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
-#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
-
-/* DSI D-PHY Layer Registers */
-#define D0W_DPHYCONTTX 0x0004
-#define CLW_DPHYCONTRX 0x0020
-#define D0W_DPHYCONTRX 0x0024
-#define D1W_DPHYCONTRX 0x0028
-#define D2W_DPHYCONTRX 0x002C
-#define D3W_DPHYCONTRX 0x0030
-#define COM_DPHYCONTRX 0x0038
-#define CLW_CNTRL 0x0040
-#define D0W_CNTRL 0x0044
-#define D1W_CNTRL 0x0048
-#define D2W_CNTRL 0x004C
-#define D3W_CNTRL 0x0050
-#define DFTMODE_CNTRL 0x0054
-
-/* DSI PPI Layer Registers */
-#define PPI_STARTPPI 0x0104
-#define PPI_BUSYPPI 0x0108
-#define PPI_LINEINITCNT 0x0110
-#define PPI_LPTXTIMECNT 0x0114
-#define PPI_LANEENABLE 0x0134
-#define PPI_TX_RX_TA 0x013C
-#define PPI_CLS_ATMR 0x0140
-#define PPI_D0S_ATMR 0x0144
-#define PPI_D1S_ATMR 0x0148
-#define PPI_D2S_ATMR 0x014C
-#define PPI_D3S_ATMR 0x0150
-#define PPI_D0S_CLRSIPOCOUNT 0x0164
-#define PPI_D1S_CLRSIPOCOUNT 0x0168
-#define PPI_D2S_CLRSIPOCOUNT 0x016C
-#define PPI_D3S_CLRSIPOCOUNT 0x0170
-#define CLS_PRE 0x0180
-#define D0S_PRE 0x0184
-#define D1S_PRE 0x0188
-#define D2S_PRE 0x018C
-#define D3S_PRE 0x0190
-#define CLS_PREP 0x01A0
-#define D0S_PREP 0x01A4
-#define D1S_PREP 0x01A8
-#define D2S_PREP 0x01AC
-#define D3S_PREP 0x01B0
-#define CLS_ZERO 0x01C0
-#define D0S_ZERO 0x01C4
-#define D1S_ZERO 0x01C8
-#define D2S_ZERO 0x01CC
-#define D3S_ZERO 0x01D0
-#define PPI_CLRFLG 0x01E0
-#define PPI_CLRSIPO 0x01E4
-#define HSTIMEOUT 0x01F0
-#define HSTIMEOUTENABLE 0x01F4
-
-/* DSI Protocol Layer Registers */
-#define DSI_STARTDSI 0x0204
-#define DSI_BUSYDSI 0x0208
-#define DSI_LANEENABLE 0x0210
-#define DSI_LANESTATUS0 0x0214
-#define DSI_LANESTATUS1 0x0218
-#define DSI_INTSTATUS 0x0220
-#define DSI_INTMASK 0x0224
-#define DSI_INTCLR 0x0228
-#define DSI_LPTXTO 0x0230
-
-/* DSI General Registers */
-#define DSIERRCNT 0x0300
-
-/* DSI Application Layer Registers */
-#define APLCTRL 0x0400
-#define RDPKTLN 0x0404
-
-/* Video Path Registers */
-#define VPCTRL 0x0450
-#define HTIM1 0x0454
-#define HTIM2 0x0458
-#define VTIM1 0x045C
-#define VTIM2 0x0460
-#define VFUEN 0x0464
-
-/* LVDS Registers */
-#define LVMX0003 0x0480
-#define LVMX0407 0x0484
-#define LVMX0811 0x0488
-#define LVMX1215 0x048C
-#define LVMX1619 0x0490
-#define LVMX2023 0x0494
-#define LVMX2427 0x0498
-#define LVCFG 0x049C
-#define LVPHY0 0x04A0
-#define LVPHY1 0x04A4
-
-/* System Registers */
-#define SYSSTAT 0x0500
-#define SYSRST 0x0504
-
-/* GPIO Registers */
-/*#define GPIOC 0x0520*/
-#define GPIOO 0x0524
-#define GPIOI 0x0528
-
-/* I2C Registers */
-#define I2CTIMCTRL 0x0540
-#define I2CMADDR 0x0544
-#define WDATAQ 0x0548
-#define RDATAQ 0x054C
-
-/* Chip/Rev Registers */
-#define IDREG 0x0580
-
-/* Debug Registers */
-#define DEBUG00 0x05A0
-#define DEBUG01 0x05A4
-
-/* Panel CABC registers */
-#define PANEL_PWM_CONTROL 0x90
-#define PANEL_FREQ_DIVIDER_HI 0x91
-#define PANEL_FREQ_DIVIDER_LO 0x92
-#define PANEL_DUTY_CONTROL 0x93
-#define PANEL_MODIFY_RGB 0x94
-#define PANEL_FRAMERATE_CONTROL 0x96
-#define PANEL_PWM_MIN 0x97
-#define PANEL_PWM_REF 0x98
-#define PANEL_PWM_MAX 0x99
-#define PANEL_ALLOW_DISTORT 0x9A
-#define PANEL_BYPASS_PWMI 0x9B
-
-/* Panel color management registers */
-#define PANEL_CM_ENABLE 0x700
-#define PANEL_CM_HUE 0x701
-#define PANEL_CM_SATURATION 0x702
-#define PANEL_CM_INTENSITY 0x703
-#define PANEL_CM_BRIGHTNESS 0x704
-#define PANEL_CM_CE_ENABLE 0x705
-#define PANEL_CM_PEAK_EN 0x710
-#define PANEL_CM_GAIN 0x711
-#define PANEL_CM_HUETABLE_START 0x730
-#define PANEL_CM_HUETABLE_END 0x747 /* inclusive */
-
-/* Input muxing for registers LVMX0003...LVMX2427 */
-enum {
- INPUT_R0, /* 0 */
- INPUT_R1,
- INPUT_R2,
- INPUT_R3,
- INPUT_R4,
- INPUT_R5,
- INPUT_R6,
- INPUT_R7,
- INPUT_G0, /* 8 */
- INPUT_G1,
- INPUT_G2,
- INPUT_G3,
- INPUT_G4,
- INPUT_G5,
- INPUT_G6,
- INPUT_G7,
- INPUT_B0, /* 16 */
- INPUT_B1,
- INPUT_B2,
- INPUT_B3,
- INPUT_B4,
- INPUT_B5,
- INPUT_B6,
- INPUT_B7,
- INPUT_HSYNC, /* 24 */
- INPUT_VSYNC,
- INPUT_DE,
- LOGIC_0,
- /* 28...31 undefined */
-};
-
-#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \
- (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \
- FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
-
-/**
- * tc35876x_regw - Write DSI-LVDS bridge register using I2C
- * @client: struct i2c_client to use
- * @reg: register address
- * @value: value to write
- *
- * Returns 0 on success, or a negative error value.
- */
-static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
-{
- int r;
- u8 tx_data[] = {
- /* NOTE: Register address big-endian, data little-endian. */
- (reg >> 8) & 0xff,
- reg & 0xff,
- value & 0xff,
- (value >> 8) & 0xff,
- (value >> 16) & 0xff,
- (value >> 24) & 0xff,
- };
- struct i2c_msg msgs[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .buf = tx_data,
- .len = ARRAY_SIZE(tx_data),
- },
- };
-
- r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (r < 0) {
- dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
- __func__, reg, value, r);
- return r;
- }
-
- if (r < ARRAY_SIZE(msgs)) {
- dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
- __func__, reg, value, r);
- return -EAGAIN;
- }
-
- dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
- __func__, reg, value);
-
- return 0;
-}
-
-/**
- * tc35876x_regr - Read DSI-LVDS bridge register using I2C
- * @client: struct i2c_client to use
- * @reg: register address
- * @value: pointer for storing the value
- *
- * Returns 0 on success, or a negative error value.
- */
-static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
-{
- int r;
- u8 tx_data[] = {
- (reg >> 8) & 0xff,
- reg & 0xff,
- };
- u8 rx_data[4];
- struct i2c_msg msgs[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .buf = tx_data,
- .len = ARRAY_SIZE(tx_data),
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .buf = rx_data,
- .len = ARRAY_SIZE(rx_data),
- },
- };
-
- r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (r < 0) {
- dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
- reg, r);
- return r;
- }
-
- if (r < ARRAY_SIZE(msgs)) {
- dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
- reg, r);
- return -EAGAIN;
- }
-
- *value = rx_data[0] << 24 | rx_data[1] << 16 |
- rx_data[2] << 8 | rx_data[3];
-
- dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
- reg, *value);
-
- return 0;
-}
-
-void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
-{
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
-
- if (!bridge_reset)
- return;
-
- if (state) {
- gpiod_set_value_cansleep(bridge_reset, 0);
- mdelay(10);
- } else {
- /* Pull MIPI Bridge reset pin to Low */
- gpiod_set_value_cansleep(bridge_reset, 0);
- mdelay(20);
- /* Pull MIPI Bridge reset pin to High */
- gpiod_set_value_cansleep(bridge_reset, 1);
- mdelay(40);
- }
-}
-
-void tc35876x_configure_lvds_bridge(struct drm_device *dev)
-{
- struct i2c_client *i2c = tc35876x_client;
- u32 ppi_lptxtimecnt;
- u32 txtagocnt;
- u32 txtasurecnt;
- u32 id;
-
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
-
- if (!tc35876x_regr(i2c, IDREG, &id))
- dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
- else
- dev_err(&tc35876x_client->dev, "Cannot read ID\n");
-
- ppi_lptxtimecnt = 4;
- txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
- txtasurecnt = 3 * ppi_lptxtimecnt / 2;
- tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
- FLD_VAL(txtasurecnt, 10, 0));
- tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
-
- tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
- tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
- tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
- tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
-
- /* Enabling MIPI & PPI lanes, Enable 4 lanes */
- tc35876x_regw(i2c, PPI_LANEENABLE,
- BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
- tc35876x_regw(i2c, DSI_LANEENABLE,
- BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
- tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
- tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
-
- /* Setting LVDS output frequency */
- tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
- FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
-
- /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
- tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
-
- /* Horizontal back porch and horizontal pulse width. 0x00280028 */
- tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
-
- /* Horizontal front porch and horizontal active video size. 0x00500500*/
- tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
-
- /* Vertical back porch and vertical sync pulse width. 0x000e000a */
- tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
-
- /* Vertical front porch and vertical display size. 0x000e0320 */
- tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
-
- /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
- tc35876x_regw(i2c, VFUEN, BIT(0));
-
- /* Soft reset LCD controller. */
- tc35876x_regw(i2c, SYSRST, BIT(2));
-
- /* LVDS-TX input muxing */
- tc35876x_regw(i2c, LVMX0003,
- INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
- tc35876x_regw(i2c, LVMX0407,
- INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
- tc35876x_regw(i2c, LVMX0811,
- INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
- tc35876x_regw(i2c, LVMX1215,
- INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
- tc35876x_regw(i2c, LVMX1619,
- INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
- tc35876x_regw(i2c, LVMX2023,
- INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5));
- tc35876x_regw(i2c, LVMX2427,
- INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
-
- /* Enable LVDS transmitter. */
- tc35876x_regw(i2c, LVCFG, BIT(0));
-
- /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
- * to 0x0288, must be in error?! */
- tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
-}
-
-#define GPIOPWMCTRL 0x38F
-#define PWM0CLKDIV0 0x62 /* low byte */
-#define PWM0CLKDIV1 0x61 /* high byte */
-
-#define SYSTEMCLK 19200000UL /* 19.2 MHz */
-#define PWM_FREQUENCY 9600 /* Hz */
-
-/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
-static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
-{
- return (baseclk - f) / f;
-}
-
-static void tc35876x_brightness_init(struct drm_device *dev)
-{
- int ret;
- u8 pwmctrl;
- u16 clkdiv;
-
- /* Make sure the PWM reference is the 19.2 MHz system clock. Read first
- * instead of setting directly to catch potential conflicts between PWM
- * users. */
- ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
- if (ret || pwmctrl != 0x01) {
- if (ret)
- dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
- else
- dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
-
- ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
- if (ret)
- dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
- }
-
- clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
-
- ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
- if (!ret)
- ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
-
- if (ret)
- dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
- else
- dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
- clkdiv, PWM_FREQUENCY);
-}
-
-#define PWM0DUTYCYCLE 0x67
-
-void tc35876x_brightness_control(struct drm_device *dev, int level)
-{
- int ret;
- u8 duty_val;
- u8 panel_duty_val;
-
- level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
-
- /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
- duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
-
- /* I won't pretend to understand this formula. The panel spec is quite
- * bad engrish.
- */
- panel_duty_val = (2 * level - 100) * 0xA9 /
- MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
-
- ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
- if (ret)
- dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
- __func__);
-
- if (cmi_lcd_i2c_client) {
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_PWM_MAX, panel_duty_val);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
- __func__);
- }
-}
-
-void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
-{
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
-
- if (bridge_bl_enable)
- gpiod_set_value_cansleep(bridge_bl_enable, 0);
-
- if (backlight_voltage)
- gpiod_set_value_cansleep(backlight_voltage, 0);
-}
-
-void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
-
- if (backlight_voltage) {
- gpiod_set_value_cansleep(backlight_voltage, 1);
- msleep(260);
- }
-
- if (cmi_lcd_i2c_client) {
- int ret;
- dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
- /* Bit 4 is average_saving. Setting it to 1, the brightness is
- * referenced to the average of the frame content. 0 means
- * reference to the maximum of frame contents. Bits 3:0 are
- * allow_distort. When set to a nonzero value, all color values
- * between 255-allow_distort*2 and 255 are mapped to the
- * 255-allow_distort*2 value.
- */
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_ALLOW_DISTORT, 0x10);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev,
- "i2c write failed (%d)\n", ret);
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_BYPASS_PWMI, 0);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev,
- "i2c write failed (%d)\n", ret);
- /* Set minimum brightness value - this is tunable */
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_PWM_MIN, 0x35);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev,
- "i2c write failed (%d)\n", ret);
- }
-
- if (bridge_bl_enable)
- gpiod_set_value_cansleep(bridge_bl_enable, 1);
-
- tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
-}
-
-static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
-
- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- /* FIXME: do this properly. */
- mode->hdisplay = 1280;
- mode->vdisplay = 800;
- mode->hsync_start = 1360;
- mode->hsync_end = 1400;
- mode->htotal = 1440;
- mode->vsync_start = 814;
- mode->vsync_end = 824;
- mode->vtotal = 838;
- mode->clock = 33324 << 1;
-
- dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
- dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
- dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
- dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
- dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
- dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
- dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
- dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
- dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-/* DV1 Active area 216.96 x 135.6 mm */
-#define DV1_PANEL_WIDTH 217
-#define DV1_PANEL_HEIGHT 136
-
-static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = DV1_PANEL_WIDTH;
- pi->height_mm = DV1_PANEL_HEIGHT;
-
- return 0;
-}
-
-static int tc35876x_bridge_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- dev_info(&client->dev, "%s\n", __func__);
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
- __func__);
- return -ENODEV;
- }
-
- bridge_reset = devm_gpiod_get_optional(&client->dev, "bridge-reset", GPIOD_OUT_LOW);
- if (IS_ERR(bridge_reset))
- return PTR_ERR(bridge_reset);
- if (bridge_reset)
- gpiod_set_consumer_name(bridge_reset, "tc35876x bridge reset");
-
- bridge_bl_enable = devm_gpiod_get_optional(&client->dev, "bl-en", GPIOD_OUT_LOW);
- if (IS_ERR(bridge_bl_enable))
- return PTR_ERR(bridge_bl_enable);
- if (bridge_bl_enable)
- gpiod_set_consumer_name(bridge_bl_enable, "tc35876x panel bl en");
-
- backlight_voltage = devm_gpiod_get_optional(&client->dev, "vadd", GPIOD_OUT_LOW);
- if (IS_ERR(backlight_voltage))
- return PTR_ERR(backlight_voltage);
- if (backlight_voltage)
- gpiod_set_consumer_name(backlight_voltage, "tc35876x panel vadd");
-
- tc35876x_client = client;
-
- return 0;
-}
-
-static int tc35876x_bridge_remove(struct i2c_client *client)
-{
- dev_dbg(&client->dev, "%s\n", __func__);
-
- tc35876x_client = NULL;
-
- return 0;
-}
-
-static const struct i2c_device_id tc35876x_bridge_id[] = {
- { "i2c_disp_brig", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
-
-static struct i2c_driver tc35876x_bridge_i2c_driver = {
- .driver = {
- .name = "i2c_disp_brig",
- },
- .id_table = tc35876x_bridge_id,
- .probe = tc35876x_bridge_probe,
- .remove = tc35876x_bridge_remove,
-};
-
-/* LCD panel I2C */
-static int cmi_lcd_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- dev_info(&client->dev, "%s\n", __func__);
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
- __func__);
- return -ENODEV;
- }
-
- cmi_lcd_i2c_client = client;
-
- return 0;
-}
-
-static int cmi_lcd_i2c_remove(struct i2c_client *client)
-{
- dev_dbg(&client->dev, "%s\n", __func__);
-
- cmi_lcd_i2c_client = NULL;
-
- return 0;
-}
-
-static const struct i2c_device_id cmi_lcd_i2c_id[] = {
- { "cmi-lcd", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
-
-static struct i2c_driver cmi_lcd_i2c_driver = {
- .driver = {
- .name = "cmi-lcd",
- },
- .id_table = cmi_lcd_i2c_id,
- .probe = cmi_lcd_i2c_probe,
- .remove = cmi_lcd_i2c_remove,
-};
-
-/* HACK to create I2C device while it's not created by platform code */
-#define CMI_LCD_I2C_ADAPTER 2
-#define CMI_LCD_I2C_ADDR 0x60
-
-static int cmi_lcd_hack_create_device(void)
-{
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- struct i2c_board_info info = {
- .type = "cmi-lcd",
- .addr = CMI_LCD_I2C_ADDR,
- };
-
- pr_debug("%s\n", __func__);
-
- adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
- if (!adapter) {
- pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
- CMI_LCD_I2C_ADAPTER);
- return -EINVAL;
- }
-
- client = i2c_new_client_device(adapter, &info);
- if (IS_ERR(client)) {
- pr_err("%s: creating I2C device failed\n", __func__);
- i2c_put_adapter(adapter);
- return PTR_ERR(client);
- }
-
- return 0;
-}
-
-static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
- .dpms = mdfld_dsi_dpi_dpms,
- .mode_fixup = mdfld_dsi_dpi_mode_fixup,
- .prepare = mdfld_dsi_dpi_prepare,
- .mode_set = mdfld_dsi_dpi_mode_set,
- .commit = mdfld_dsi_dpi_commit,
-};
-
-const struct panel_funcs mdfld_tc35876x_funcs = {
- .encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
- .get_config_mode = tc35876x_get_config_mode,
- .get_panel_info = tc35876x_get_panel_info,
-};
-
-void tc35876x_init(struct drm_device *dev)
-{
- int r;
-
- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
-
- cmi_lcd_hack_create_device();
-
- r = i2c_add_driver(&cmi_lcd_i2c_driver);
- if (r < 0)
- dev_err(&dev->pdev->dev,
- "%s: i2c_add_driver() for %s failed (%d)\n",
- __func__, cmi_lcd_i2c_driver.driver.name, r);
-
- r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
- if (r < 0)
- dev_err(&dev->pdev->dev,
- "%s: i2c_add_driver() for %s failed (%d)\n",
- __func__, tc35876x_bridge_i2c_driver.driver.name, r);
-
- tc35876x_brightness_init(dev);
-}
-
-void tc35876x_exit(void)
-{
- pr_debug("%s\n", __func__);
-
- i2c_del_driver(&tc35876x_bridge_i2c_driver);
-
- if (cmi_lcd_i2c_client)
- i2c_del_driver(&cmi_lcd_i2c_driver);
-}