^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright © 2011 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Permission is hereby granted, free of charge, to any person obtaining a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * copy of this software and associated documentation files (the "Software"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * to deal in the Software without restriction, including without limitation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * the rights to use, copy, modify, merge, publish, distribute, sublicense,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * and/or sell copies of the Software, and to permit persons to whom the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Software is furnished to do so, subject to the following conditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * The above copyright notice and this permission notice (including the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * paragraph) shall be included in all copies or substantial portions of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * DEALINGS IN THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/intel_scu_ipc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "mdfld_dsi_dpi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "mdfld_dsi_pkg_sender.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "mdfld_output.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include "tc35876x-dsi-lvds.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static struct i2c_client *tc35876x_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct i2c_client *cmi_lcd_i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* Panel GPIOs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static struct gpio_desc *bridge_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static struct gpio_desc *bridge_bl_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static struct gpio_desc *backlight_voltage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* DSI D-PHY Layer Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define D0W_DPHYCONTTX 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define CLW_DPHYCONTRX 0x0020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define D0W_DPHYCONTRX 0x0024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define D1W_DPHYCONTRX 0x0028
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define D2W_DPHYCONTRX 0x002C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define D3W_DPHYCONTRX 0x0030
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define COM_DPHYCONTRX 0x0038
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CLW_CNTRL 0x0040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define D0W_CNTRL 0x0044
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define D1W_CNTRL 0x0048
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define D2W_CNTRL 0x004C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define D3W_CNTRL 0x0050
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define DFTMODE_CNTRL 0x0054
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* DSI PPI Layer Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define PPI_STARTPPI 0x0104
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define PPI_BUSYPPI 0x0108
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define PPI_LINEINITCNT 0x0110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define PPI_LPTXTIMECNT 0x0114
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define PPI_LANEENABLE 0x0134
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define PPI_TX_RX_TA 0x013C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define PPI_CLS_ATMR 0x0140
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define PPI_D0S_ATMR 0x0144
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define PPI_D1S_ATMR 0x0148
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define PPI_D2S_ATMR 0x014C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define PPI_D3S_ATMR 0x0150
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define PPI_D0S_CLRSIPOCOUNT 0x0164
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define PPI_D1S_CLRSIPOCOUNT 0x0168
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define PPI_D2S_CLRSIPOCOUNT 0x016C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define PPI_D3S_CLRSIPOCOUNT 0x0170
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define CLS_PRE 0x0180
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define D0S_PRE 0x0184
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define D1S_PRE 0x0188
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define D2S_PRE 0x018C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define D3S_PRE 0x0190
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define CLS_PREP 0x01A0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define D0S_PREP 0x01A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define D1S_PREP 0x01A8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define D2S_PREP 0x01AC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define D3S_PREP 0x01B0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define CLS_ZERO 0x01C0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define D0S_ZERO 0x01C4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define D1S_ZERO 0x01C8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define D2S_ZERO 0x01CC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define D3S_ZERO 0x01D0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define PPI_CLRFLG 0x01E0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define PPI_CLRSIPO 0x01E4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define HSTIMEOUT 0x01F0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define HSTIMEOUTENABLE 0x01F4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* DSI Protocol Layer Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define DSI_STARTDSI 0x0204
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define DSI_BUSYDSI 0x0208
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define DSI_LANEENABLE 0x0210
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define DSI_LANESTATUS0 0x0214
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define DSI_LANESTATUS1 0x0218
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define DSI_INTSTATUS 0x0220
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define DSI_INTMASK 0x0224
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define DSI_INTCLR 0x0228
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define DSI_LPTXTO 0x0230
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* DSI General Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define DSIERRCNT 0x0300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* DSI Application Layer Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define APLCTRL 0x0400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define RDPKTLN 0x0404
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Video Path Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define VPCTRL 0x0450
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define HTIM1 0x0454
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define HTIM2 0x0458
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define VTIM1 0x045C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define VTIM2 0x0460
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define VFUEN 0x0464
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* LVDS Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define LVMX0003 0x0480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define LVMX0407 0x0484
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define LVMX0811 0x0488
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define LVMX1215 0x048C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define LVMX1619 0x0490
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define LVMX2023 0x0494
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define LVMX2427 0x0498
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define LVCFG 0x049C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define LVPHY0 0x04A0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define LVPHY1 0x04A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* System Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define SYSSTAT 0x0500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define SYSRST 0x0504
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* GPIO Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*#define GPIOC 0x0520*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define GPIOO 0x0524
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define GPIOI 0x0528
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* I2C Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define I2CTIMCTRL 0x0540
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define I2CMADDR 0x0544
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define WDATAQ 0x0548
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define RDATAQ 0x054C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* Chip/Rev Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define IDREG 0x0580
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* Debug Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define DEBUG00 0x05A0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define DEBUG01 0x05A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Panel CABC registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define PANEL_PWM_CONTROL 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define PANEL_FREQ_DIVIDER_HI 0x91
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define PANEL_FREQ_DIVIDER_LO 0x92
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define PANEL_DUTY_CONTROL 0x93
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define PANEL_MODIFY_RGB 0x94
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define PANEL_FRAMERATE_CONTROL 0x96
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define PANEL_PWM_MIN 0x97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define PANEL_PWM_REF 0x98
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define PANEL_PWM_MAX 0x99
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define PANEL_ALLOW_DISTORT 0x9A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define PANEL_BYPASS_PWMI 0x9B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* Panel color management registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define PANEL_CM_ENABLE 0x700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define PANEL_CM_HUE 0x701
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define PANEL_CM_SATURATION 0x702
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define PANEL_CM_INTENSITY 0x703
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define PANEL_CM_BRIGHTNESS 0x704
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define PANEL_CM_CE_ENABLE 0x705
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define PANEL_CM_PEAK_EN 0x710
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define PANEL_CM_GAIN 0x711
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define PANEL_CM_HUETABLE_START 0x730
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define PANEL_CM_HUETABLE_END 0x747 /* inclusive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* Input muxing for registers LVMX0003...LVMX2427 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) INPUT_R0, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) INPUT_R1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) INPUT_R2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) INPUT_R3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) INPUT_R4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) INPUT_R5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) INPUT_R6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) INPUT_R7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) INPUT_G0, /* 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) INPUT_G1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) INPUT_G2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) INPUT_G3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) INPUT_G4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) INPUT_G5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) INPUT_G6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) INPUT_G7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) INPUT_B0, /* 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) INPUT_B1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) INPUT_B2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) INPUT_B3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) INPUT_B4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) INPUT_B5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) INPUT_B6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) INPUT_B7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) INPUT_HSYNC, /* 24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) INPUT_VSYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) INPUT_DE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) LOGIC_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* 28...31 undefined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * tc35876x_regw - Write DSI-LVDS bridge register using I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @client: struct i2c_client to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @reg: register address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @value: value to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Returns 0 on success, or a negative error value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) u8 tx_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* NOTE: Register address big-endian, data little-endian. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) (reg >> 8) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) reg & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) value & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) (value >> 8) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) (value >> 16) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) (value >> 24) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct i2c_msg msgs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .addr = client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .buf = tx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .len = ARRAY_SIZE(tx_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (r < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) __func__, reg, value, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (r < ARRAY_SIZE(msgs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) __func__, reg, value, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) __func__, reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * tc35876x_regr - Read DSI-LVDS bridge register using I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * @client: struct i2c_client to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * @reg: register address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * @value: pointer for storing the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * Returns 0 on success, or a negative error value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u8 tx_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) (reg >> 8) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) reg & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u8 rx_data[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct i2c_msg msgs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .addr = client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .buf = tx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .len = ARRAY_SIZE(tx_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .addr = client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .buf = rx_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .len = ARRAY_SIZE(rx_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (r < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) reg, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (r < ARRAY_SIZE(msgs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) reg, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) *value = rx_data[0] << 24 | rx_data[1] << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) rx_data[2] << 8 | rx_data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) reg, *value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (WARN(!tc35876x_client, "%s called before probe", __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!bridge_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) gpiod_set_value_cansleep(bridge_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* Pull MIPI Bridge reset pin to Low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) gpiod_set_value_cansleep(bridge_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) mdelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* Pull MIPI Bridge reset pin to High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) gpiod_set_value_cansleep(bridge_reset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) mdelay(40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) void tc35876x_configure_lvds_bridge(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct i2c_client *i2c = tc35876x_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) u32 ppi_lptxtimecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u32 txtagocnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) u32 txtasurecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (WARN(!tc35876x_client, "%s called before probe", __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!tc35876x_regr(i2c, IDREG, &id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) dev_err(&tc35876x_client->dev, "Cannot read ID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ppi_lptxtimecnt = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) txtasurecnt = 3 * ppi_lptxtimecnt / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) FLD_VAL(txtasurecnt, 10, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Enabling MIPI & PPI lanes, Enable 4 lanes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) tc35876x_regw(i2c, PPI_LANEENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) tc35876x_regw(i2c, DSI_LANEENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* Setting LVDS output frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* Horizontal back porch and horizontal pulse width. 0x00280028 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Horizontal front porch and horizontal active video size. 0x00500500*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* Vertical back porch and vertical sync pulse width. 0x000e000a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* Vertical front porch and vertical display size. 0x000e0320 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) tc35876x_regw(i2c, VFUEN, BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* Soft reset LCD controller. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) tc35876x_regw(i2c, SYSRST, BIT(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* LVDS-TX input muxing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) tc35876x_regw(i2c, LVMX0003,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) tc35876x_regw(i2c, LVMX0407,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) tc35876x_regw(i2c, LVMX0811,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) tc35876x_regw(i2c, LVMX1215,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) tc35876x_regw(i2c, LVMX1619,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) tc35876x_regw(i2c, LVMX2023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) tc35876x_regw(i2c, LVMX2427,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Enable LVDS transmitter. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) tc35876x_regw(i2c, LVCFG, BIT(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * to 0x0288, must be in error?! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) #define GPIOPWMCTRL 0x38F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) #define PWM0CLKDIV0 0x62 /* low byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #define PWM0CLKDIV1 0x61 /* high byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) #define SYSTEMCLK 19200000UL /* 19.2 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) #define PWM_FREQUENCY 9600 /* Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return (baseclk - f) / f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void tc35876x_brightness_init(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) u8 pwmctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u16 clkdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* Make sure the PWM reference is the 19.2 MHz system clock. Read first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * instead of setting directly to catch potential conflicts between PWM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * users. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (ret || pwmctrl != 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) clkdiv, PWM_FREQUENCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) #define PWM0DUTYCYCLE 0x67
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) void tc35876x_brightness_control(struct drm_device *dev, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) u8 duty_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) u8 panel_duty_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* I won't pretend to understand this formula. The panel spec is quite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * bad engrish.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) panel_duty_val = (2 * level - 100) * 0xA9 /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (cmi_lcd_i2c_client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) PANEL_PWM_MAX, panel_duty_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (WARN(!tc35876x_client, "%s called before probe", __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (bridge_bl_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) gpiod_set_value_cansleep(bridge_bl_enable, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (backlight_voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) gpiod_set_value_cansleep(backlight_voltage, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (WARN(!tc35876x_client, "%s called before probe", __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (backlight_voltage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) gpiod_set_value_cansleep(backlight_voltage, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) msleep(260);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (cmi_lcd_i2c_client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* Bit 4 is average_saving. Setting it to 1, the brightness is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * referenced to the average of the frame content. 0 means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * reference to the maximum of frame contents. Bits 3:0 are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * allow_distort. When set to a nonzero value, all color values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * between 255-allow_distort*2 and 255 are mapped to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * 255-allow_distort*2 value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) PANEL_ALLOW_DISTORT, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) dev_err(&cmi_lcd_i2c_client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) "i2c write failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) PANEL_BYPASS_PWMI, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dev_err(&cmi_lcd_i2c_client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) "i2c write failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* Set minimum brightness value - this is tunable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) PANEL_PWM_MIN, 0x35);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dev_err(&cmi_lcd_i2c_client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) "i2c write failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (bridge_bl_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) gpiod_set_value_cansleep(bridge_bl_enable, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) dev_dbg(&dev->pdev->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) mode = kzalloc(sizeof(*mode), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* FIXME: do this properly. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) mode->hdisplay = 1280;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) mode->vdisplay = 800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) mode->hsync_start = 1360;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mode->hsync_end = 1400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) mode->htotal = 1440;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) mode->vsync_start = 814;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) mode->vsync_end = 824;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) mode->vtotal = 838;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) mode->clock = 33324 << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) drm_mode_set_name(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) drm_mode_set_crtcinfo(mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) mode->type |= DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* DV1 Active area 216.96 x 135.6 mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) #define DV1_PANEL_WIDTH 217
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) #define DV1_PANEL_HEIGHT 136
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct panel_info *pi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (!dev || !pi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) pi->width_mm = DV1_PANEL_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) pi->height_mm = DV1_PANEL_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static int tc35876x_bridge_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) dev_info(&client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) bridge_reset = devm_gpiod_get_optional(&client->dev, "bridge-reset", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (IS_ERR(bridge_reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return PTR_ERR(bridge_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (bridge_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) gpiod_set_consumer_name(bridge_reset, "tc35876x bridge reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) bridge_bl_enable = devm_gpiod_get_optional(&client->dev, "bl-en", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (IS_ERR(bridge_bl_enable))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return PTR_ERR(bridge_bl_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (bridge_bl_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) gpiod_set_consumer_name(bridge_bl_enable, "tc35876x panel bl en");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) backlight_voltage = devm_gpiod_get_optional(&client->dev, "vadd", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (IS_ERR(backlight_voltage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return PTR_ERR(backlight_voltage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (backlight_voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) gpiod_set_consumer_name(backlight_voltage, "tc35876x panel vadd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) tc35876x_client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static int tc35876x_bridge_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) dev_dbg(&client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) tc35876x_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static const struct i2c_device_id tc35876x_bridge_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) { "i2c_disp_brig", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static struct i2c_driver tc35876x_bridge_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) .name = "i2c_disp_brig",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) .id_table = tc35876x_bridge_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) .probe = tc35876x_bridge_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) .remove = tc35876x_bridge_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* LCD panel I2C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static int cmi_lcd_i2c_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) dev_info(&client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) cmi_lcd_i2c_client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static int cmi_lcd_i2c_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) dev_dbg(&client->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) cmi_lcd_i2c_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static const struct i2c_device_id cmi_lcd_i2c_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) { "cmi-lcd", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) static struct i2c_driver cmi_lcd_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .name = "cmi-lcd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) .id_table = cmi_lcd_i2c_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) .probe = cmi_lcd_i2c_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) .remove = cmi_lcd_i2c_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* HACK to create I2C device while it's not created by platform code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) #define CMI_LCD_I2C_ADAPTER 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) #define CMI_LCD_I2C_ADDR 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) static int cmi_lcd_hack_create_device(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct i2c_adapter *adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) struct i2c_board_info info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .type = "cmi-lcd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .addr = CMI_LCD_I2C_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (!adapter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) CMI_LCD_I2C_ADAPTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) client = i2c_new_client_device(adapter, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (IS_ERR(client)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) pr_err("%s: creating I2C device failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) i2c_put_adapter(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return PTR_ERR(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .dpms = mdfld_dsi_dpi_dpms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .mode_fixup = mdfld_dsi_dpi_mode_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .prepare = mdfld_dsi_dpi_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) .mode_set = mdfld_dsi_dpi_mode_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) .commit = mdfld_dsi_dpi_commit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) const struct panel_funcs mdfld_tc35876x_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .get_config_mode = tc35876x_get_config_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .get_panel_info = tc35876x_get_panel_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) void tc35876x_init(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) dev_dbg(&dev->pdev->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) cmi_lcd_hack_create_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) r = i2c_add_driver(&cmi_lcd_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) dev_err(&dev->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) "%s: i2c_add_driver() for %s failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) __func__, cmi_lcd_i2c_driver.driver.name, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) dev_err(&dev->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) "%s: i2c_add_driver() for %s failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) __func__, tc35876x_bridge_i2c_driver.driver.name, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) tc35876x_brightness_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) void tc35876x_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) i2c_del_driver(&tc35876x_bridge_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (cmi_lcd_i2c_client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) i2c_del_driver(&cmi_lcd_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }