Add mdss_rgb driver to drive RGB parallel interface required on qcs405 target. Also added an SPI controller to transfer panel on/off sequences to RGB panel. Change-Id: I5479a05aa9e0fbc922dabed9a4b85cec1fa167d3 Signed-off-by: Rashi Bindra <rbindra@codeaurora.org> Signed-off-by: Narender Ankam <nankam@codeaurora.org>tirimbino
parent
4b54d9aab0
commit
f86f7bcd2c
@ -0,0 +1,153 @@ |
||||
Qualcomm Technologies, Inc. mdss-rgb |
||||
|
||||
mdss-rgb is the master RGB device which supports software RGB interface. |
||||
|
||||
Required properties: |
||||
- compatible: Must be "qcom,mdss-rgb" |
||||
- ranges: The standard property which specifies the child address |
||||
- reg: Base address and length of the different register |
||||
regions(s) required for RGB functionality. |
||||
- reg-names: A list of strings that map in order to the list of regs. |
||||
"dsi_phy" - MDSS DSI PHY register region |
||||
"dsi_phy_regulator" - MDSS DSI PHY REGULATOR region |
||||
"mmss_misc_phys" - Register region for MMSS DSI clamps |
||||
- vdda-supply: Phandle for vdda regulator device node. |
||||
- vddio-supply: Phandle for vddio regulator device node. |
||||
- qcom,mdss-mdp: pHandle that specifies the mdss-mdp device. |
||||
- qcom,mdss-fb-map: pHandle that specifies the framebuffer to which the |
||||
|
||||
- qcom,platform-reset-gpio: Specifies the panel reset gpio. |
||||
- pinctrl-names: List of names to assign mdss pin states defined in pinctrl device node |
||||
Refer to pinctrl-bindings.txt |
||||
- pinctrl-<0..n>: Lists phandles each pointing to the pin configuration node within a pin |
||||
controller. These pin configurations are installed in the pinctrl |
||||
device node. Refer to pinctrl-bindings.txt |
||||
|
||||
- qcom,<type>-supply-entries: A node that lists the elements of the supply used by the |
||||
a particular "type" of RGB modulee. The module "types" |
||||
can be "core", "ctrl", and "phy". Within the same type, |
||||
there can be more than one instance of this binding, |
||||
in which case the entry would be appended with the |
||||
supply entry index. |
||||
e.g. qcom,ctrl-supply-entry@0 |
||||
-- qcom,supply-name: name of the supply (vdd/vdda/vddio) |
||||
-- qcom,supply-min-voltage: minimum voltage level (uV) |
||||
-- qcom,supply-max-voltage: maximum voltage level (uV) |
||||
-- qcom,supply-enable-load: load drawn (uA) from enabled supply |
||||
-- qcom,supply-disable-load: load drawn (uA) from disabled supply |
||||
-- qcom,supply-ulp-load: load drawn (uA) from supply in ultra-low power mode |
||||
-- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on |
||||
-- qcom,supply-post-on-sleep: time to sleep (ms) after turning on |
||||
-- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off |
||||
-- qcom,supply-post-off-sleep: time to sleep (ms) after turning off |
||||
|
||||
|
||||
Example: |
||||
mdss_rgb: qcom,mdss_rgb { |
||||
compatible = "qcom,mdss-rgb"; |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
|
||||
ranges = <0x1a94400 0x1a94400 0x280 |
||||
0x1a94b80 0x1a94b80 0x30 |
||||
0x193e000 0x193e000 0x30>; |
||||
|
||||
reg = <0x1a94400 0x280>, |
||||
<0x1a94b80 0x30>, |
||||
<0x193e000 0x30>; |
||||
reg-names = "dsi_phy", |
||||
"dsi_phy_regulator", "mmss_misc_phys"; |
||||
|
||||
gdsc-supply = <&gdsc_mdss>; |
||||
vdda-1p2-supply = <&pms405_l4>; |
||||
vdda-1p8-supply = <&pms405_l5>; |
||||
vddio-supply = <&pms405_l6>; |
||||
|
||||
qcom,mdss-fb-map = <&mdss_fb0>; |
||||
qcom,mdss-mdp = <&mdss_mdp>; |
||||
|
||||
pinctrl-names = "mdss_default", "mdss_sleep"; |
||||
pinctrl-0 = <&mdss_rgb_active &mdss_rgb_data0_active |
||||
&mdss_rgb_data1_active &mdss_rgb_data2_active |
||||
&mdss_rgb_data3_active &mdss_rgb_data4_active |
||||
&mdss_rgb_data5_active &mdss_rgb_data_b0_active |
||||
&mdss_rgb_data_b1_active &mdss_rgb_data_b2_active |
||||
&mdss_rgb_data_b3_active &mdss_rgb_data_b4_active |
||||
&mdss_rgb_data_b5_active &mdss_rgb_hsync_active |
||||
&mdss_rgb_vsync_active &mdss_rgb_de_active |
||||
&mdss_rgb_clk_active>; |
||||
pinctrl-1 = <&mdss_rgb_suspend &mdss_rgb_data0_suspend |
||||
&mdss_rgb_data1_suspend &mdss_rgb_data2_suspend |
||||
&mdss_rgb_data3_suspend &mdss_rgb_data4_suspend |
||||
&mdss_rgb_data5_suspend &mdss_rgb_data_b0_suspend |
||||
&mdss_rgb_data_b1_suspend &mdss_rgb_data_b2_suspend |
||||
&mdss_rgb_data_b3_suspend &mdss_rgb_data_b4_suspend |
||||
&mdss_rgb_data_b5_suspend &mdss_rgb_hsync_suspend |
||||
&mdss_rgb_vsync_suspend &mdss_rgb_de_suspend |
||||
&mdss_rgb_clk_suspend>; |
||||
qcom,platform-reset-gpio = <&tlmm 58 0>; |
||||
|
||||
qcom,core-supply-entries { |
||||
#address-cells = <1>; |
||||
#size-cells = <0>; |
||||
|
||||
qcom,core-supply-entry@0 { |
||||
reg = <0>; |
||||
qcom,supply-name = "gdsc"; |
||||
qcom,supply-min-voltage = <0>; |
||||
qcom,supply-max-voltage = <0>; |
||||
qcom,supply-enable-load = <0>; |
||||
qcom,supply-disable-load = <0>; |
||||
}; |
||||
}; |
||||
|
||||
qcom,ctrl-supply-entries { |
||||
#address-cells = <1>; |
||||
#size-cells = <0>; |
||||
|
||||
qcom,ctrl-supply-entry@0 { |
||||
reg = <0>; |
||||
qcom,supply-name = "vdda-1p2"; |
||||
qcom,supply-min-voltage = <1200000>; |
||||
qcom,supply-max-voltage = <1200000>; |
||||
qcom,supply-enable-load = <100000>; |
||||
qcom,supply-disable-load = <100>; |
||||
qcom,supply-post-on-sleep = <20>; |
||||
}; |
||||
}; |
||||
|
||||
qcom,phy-supply-entries { |
||||
#address-cells = <1>; |
||||
#size-cells = <0>; |
||||
|
||||
qcom,phy-supply-entry@0 { |
||||
reg = <0>; |
||||
qcom,supply-name = "vdda-1p8"; |
||||
qcom,supply-min-voltage = <1800000>; |
||||
qcom,supply-max-voltage = <1800000>; |
||||
qcom,supply-enable-load = <100000>; |
||||
qcom,supply-disable-load = <100>; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
mdss-rgb-spi is the SPI controller for RGB device which supports control |
||||
commands communication with RGB panel. |
||||
|
||||
Required properties: |
||||
- compatible: Must be "qcom,mdss-rgb-spi" |
||||
- spi-max-frequency : Maximum SPI clocking speed of device in Hz |
||||
|
||||
Optional properties: |
||||
- label: A string used to describe the controller used. |
||||
- spi-cpol : Empty property indicating device requires inverse |
||||
clock polarity (CPOL) mode |
||||
- spi-cpha : Empty property indicating device requires shifted |
||||
clock phase (CPHA) mode |
||||
|
||||
Example: |
||||
mdss_rgb_spi: qcom,mdss_rgb_spi { |
||||
compatible = "qcom,mdss-rgb-spi"; |
||||
label = "MDSS SPI QUP1 CLIENT"; |
||||
spi-max-frequency = <5000000>; |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,104 @@ |
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 and |
||||
* only version 2 as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
*/ |
||||
|
||||
#include "mdss_panel.h" |
||||
#include "mdss_dsi_clk.h" |
||||
#include "mdss_dsi.h" |
||||
|
||||
#define NONE_PANEL "none" |
||||
#define DSIPHY_CMN_CTRL_0 0x001c |
||||
#define DSIPHY_CMN_CTRL_1 0x0020 |
||||
#define DSIPHY_CMN_LDO_CNTRL 0x004c |
||||
#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018 |
||||
#define DSIPHY_PLL_CLKBUFLR_EN 0x041c |
||||
|
||||
struct mdss_rgb_data { |
||||
int ndx; |
||||
bool res_init; |
||||
struct platform_device *pdev; |
||||
struct spi_device *spi; |
||||
unsigned char *ctrl_base; |
||||
struct dss_io_data ctrl_io; |
||||
struct dss_io_data phy_io; |
||||
int reg_size; |
||||
u32 *dbg_bus; |
||||
int dbg_bus_size; |
||||
u32 hw_config; /* RGB setup configuration i.e. single*/ |
||||
u32 pll_src_config; /* PLL source selection for RGB clocks */ |
||||
u32 hw_rev; /* DSI h/w revision */ |
||||
struct mdss_panel_data panel_data; |
||||
bool refresh_clk_rate; |
||||
struct clk *pixel_clk_rgb; |
||||
struct clk *byte_clk_rgb; |
||||
u32 pclk_rate; |
||||
u32 byte_clk_rate; |
||||
|
||||
/* DSI core regulators */ |
||||
struct dss_module_power panel_power_data; |
||||
struct dss_module_power power_data[DSI_MAX_PM]; |
||||
|
||||
/* DSI bus clocks */ |
||||
struct clk *mdp_core_clk; |
||||
struct clk *mnoc_clk; |
||||
struct clk *ahb_clk; |
||||
struct clk *axi_clk; |
||||
struct clk *mmss_misc_ahb_clk; |
||||
|
||||
struct clk *ext_pixel0_clk; |
||||
struct clk *ext_byte0_clk; |
||||
//struct clk *ext_pixel1_clk;
|
||||
struct clk *byte_clk_rcg; |
||||
struct clk *pixel_clk_rcg; |
||||
struct clk *byte0_parent; |
||||
struct clk *pixel0_parent; |
||||
|
||||
void *clk_mngr; |
||||
void *clk_handle; |
||||
void *mdp_clk_handle; |
||||
|
||||
/* Data bus(AXI) scale settings */ |
||||
struct msm_bus_scale_pdata *bus_scale_table; |
||||
u32 bus_handle; |
||||
u32 bus_refcount; |
||||
|
||||
int bklt_ctrl; /* backlight ctrl */ |
||||
int pwm_enabled; |
||||
struct pwm_device *pwm_bl; |
||||
struct dsi_pinctrl_res pin_res; |
||||
|
||||
u8 ctrl_state; |
||||
bool core_power; |
||||
|
||||
/* GPIOs */ |
||||
int rst_gpio; |
||||
|
||||
int (*on)(struct mdss_panel_data *pdata); |
||||
int (*off)(struct mdss_panel_data *pdata); |
||||
|
||||
}; |
||||
|
||||
enum mdss_rgb_hw_config { |
||||
SINGLE_RGB, |
||||
}; |
||||
|
||||
int mdss_rgb_panel_init(struct device_node *node, |
||||
struct mdss_rgb_data *rgb_data); |
||||
int mdss_rgb_clk_refresh(struct mdss_rgb_data *rgb_data); |
||||
int mdss_rgb_clk_div_config(struct mdss_rgb_data *rgb_data, |
||||
struct mdss_panel_info *panel_info, int frame_rate); |
||||
int rgb_panel_device_register(struct platform_device *ctrl_pdev, |
||||
struct device_node *pan_node, struct mdss_rgb_data *rgb_data); |
||||
int mdss_rgb_write_command(struct mdss_rgb_data *rgb_data, u8 cmd); |
||||
int mdss_rgb_write_data(struct mdss_rgb_data *rgb_data, u8 data); |
||||
int mdss_rgb_read_command(struct mdss_rgb_data *rgb_data, |
||||
u8 cmd, u8 *data, u8 data_len); |
@ -0,0 +1,458 @@ |
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 and |
||||
* only version 2 as published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#include <linux/of_device.h> |
||||
#include <linux/delay.h> |
||||
#include <video/mipi_display.h> |
||||
#include <linux/pwm.h> |
||||
|
||||
#include "mdss_rgb.h" |
||||
|
||||
#define RAMCTRL_CMD 0xb0 |
||||
#define RGBCTRL_CMD 0xb1 |
||||
#define PORCTRL_CMD 0xb2 |
||||
#define GCTRL_CMD 0xb7 |
||||
#define VCOMS_CMD 0xbb |
||||
#define LCMCTRL_CMD 0xc0 |
||||
#define VDVVRHEN_CMD 0xc2 |
||||
#define VRHS_CMD 0xc3 |
||||
#define VDVS_CMD 0xc4 |
||||
#define VCMOFSET_CMD 0xc5 |
||||
#define FRCTRL2_CMD 0xc6 |
||||
#define PWCTRL1_CMD 0xd0 |
||||
#define PVGAMCTRL_CMD 0xe0 |
||||
#define NVGAMCTRL_CMD 0xe1 |
||||
#define SPI2EN_CMD 0xe7 |
||||
#define PWCTRL2_CMD 0xe8 |
||||
|
||||
static void mdss_rgb_panel_reset(struct mdss_rgb_data *rgb_data) |
||||
{ |
||||
if (gpio_is_valid(rgb_data->rst_gpio)) { |
||||
gpio_set_value(rgb_data->rst_gpio, 1); |
||||
usleep_range(10000, 20000); |
||||
gpio_set_value(rgb_data->rst_gpio, 0); |
||||
usleep_range(10000, 20000); |
||||
gpio_set_value(rgb_data->rst_gpio, 1); |
||||
usleep_range(10000, 20000); |
||||
} |
||||
} |
||||
|
||||
static int mdss_rgb_panel_on(struct mdss_panel_data *pdata) |
||||
{ |
||||
struct mdss_rgb_data *rgb_data = NULL; |
||||
|
||||
if (pdata == NULL) { |
||||
pr_err("%s: invalid mdss panel data\n", __func__); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
rgb_data = container_of(pdata, struct mdss_rgb_data, |
||||
panel_data); |
||||
|
||||
mdss_rgb_panel_reset(rgb_data); |
||||
|
||||
mdss_rgb_write_command(rgb_data, MIPI_DCS_EXIT_SLEEP_MODE); |
||||
msleep(120); |
||||
|
||||
/* display and color format setting */ |
||||
mdss_rgb_write_command(rgb_data, MIPI_DCS_SET_ADDRESS_MODE); |
||||
mdss_rgb_write_data(rgb_data, 0x00); |
||||
|
||||
mdss_rgb_write_command(rgb_data, MIPI_DCS_SET_PIXEL_FORMAT); |
||||
mdss_rgb_write_data(rgb_data, 0x06); |
||||
|
||||
/* frame rate setting */ |
||||
/* RAM Control */ |
||||
mdss_rgb_write_command(rgb_data, RAMCTRL_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x11); |
||||
mdss_rgb_write_data(rgb_data, 0xf0); |
||||
|
||||
/* RGB Interface control */ |
||||
mdss_rgb_write_command(rgb_data, RGBCTRL_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x4c); |
||||
mdss_rgb_write_data(rgb_data, 0x05); |
||||
mdss_rgb_write_data(rgb_data, 0x14); |
||||
|
||||
/* Porch setting */ |
||||
mdss_rgb_write_command(rgb_data, PORCTRL_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x0c); |
||||
mdss_rgb_write_data(rgb_data, 0x0c); |
||||
mdss_rgb_write_data(rgb_data, 0x00); |
||||
mdss_rgb_write_data(rgb_data, 0x33); |
||||
mdss_rgb_write_data(rgb_data, 0x33); |
||||
|
||||
/* Gate Control */ |
||||
mdss_rgb_write_command(rgb_data, GCTRL_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x35); |
||||
/* VGH=13.26V, VGL=-10.43V */ |
||||
|
||||
/* Power setting */ |
||||
/* vcom setting */ |
||||
mdss_rgb_write_command(rgb_data, VCOMS_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x19); /* 1.05 */ |
||||
|
||||
/* LCM Control */ |
||||
mdss_rgb_write_command(rgb_data, LCMCTRL_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x2c); |
||||
|
||||
/* VDV and VRH Command Enable */ |
||||
mdss_rgb_write_command(rgb_data, VDVVRHEN_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x01); |
||||
|
||||
/* VRH Set, VAP(GVDD) & VAN(GVCL) */ |
||||
mdss_rgb_write_command(rgb_data, VRHS_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x1d); |
||||
|
||||
/* set VDV */ |
||||
mdss_rgb_write_command(rgb_data, VDVS_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x20); /* VDV=0V */ |
||||
|
||||
/* vcom Offset Set */ |
||||
mdss_rgb_write_command(rgb_data, VCMOFSET_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x20); /* vcom Offset=0V */ |
||||
|
||||
/* Frame rate control in normal mode */ |
||||
mdss_rgb_write_command(rgb_data, FRCTRL2_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x0f); /* dot inversion & 60Hz */ |
||||
|
||||
/* Power control 1 */ |
||||
mdss_rgb_write_command(rgb_data, PWCTRL1_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0xa4); |
||||
/* AVDD=6.8V; AVCL=-4.8V; VDDS=2.3V */ |
||||
mdss_rgb_write_data(rgb_data, 0xa1); |
||||
|
||||
/* Power control 2 */ |
||||
mdss_rgb_write_command(rgb_data, PWCTRL2_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x83); |
||||
|
||||
/* Set Gamma */ |
||||
mdss_rgb_write_command(rgb_data, PVGAMCTRL_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0xd2); |
||||
mdss_rgb_write_data(rgb_data, 0x13); |
||||
mdss_rgb_write_data(rgb_data, 0x16); |
||||
mdss_rgb_write_data(rgb_data, 0x0d); |
||||
mdss_rgb_write_data(rgb_data, 0x0f); |
||||
mdss_rgb_write_data(rgb_data, 0x38); |
||||
mdss_rgb_write_data(rgb_data, 0x3d); |
||||
mdss_rgb_write_data(rgb_data, 0x43); |
||||
mdss_rgb_write_data(rgb_data, 0x4d); |
||||
mdss_rgb_write_data(rgb_data, 0x1b); |
||||
mdss_rgb_write_data(rgb_data, 0x16); |
||||
mdss_rgb_write_data(rgb_data, 0x14); |
||||
mdss_rgb_write_data(rgb_data, 0x1b); |
||||
mdss_rgb_write_data(rgb_data, 0x1f); |
||||
|
||||
/* Set Gamma */ |
||||
mdss_rgb_write_command(rgb_data, NVGAMCTRL_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0xd2); |
||||
mdss_rgb_write_data(rgb_data, 0x13); |
||||
mdss_rgb_write_data(rgb_data, 0x16); |
||||
mdss_rgb_write_data(rgb_data, 0x0d); |
||||
mdss_rgb_write_data(rgb_data, 0x0f); |
||||
mdss_rgb_write_data(rgb_data, 0x38); |
||||
mdss_rgb_write_data(rgb_data, 0x3d); |
||||
mdss_rgb_write_data(rgb_data, 0x43); |
||||
mdss_rgb_write_data(rgb_data, 0x4d); |
||||
mdss_rgb_write_data(rgb_data, 0x1b); |
||||
mdss_rgb_write_data(rgb_data, 0x16); |
||||
mdss_rgb_write_data(rgb_data, 0x14); |
||||
mdss_rgb_write_data(rgb_data, 0x1b); |
||||
mdss_rgb_write_data(rgb_data, 0x1f); |
||||
|
||||
/* SPI2 Enable */ |
||||
mdss_rgb_write_command(rgb_data, SPI2EN_CMD); |
||||
mdss_rgb_write_data(rgb_data, 0x10); /* Enable 2 data lane mode */ |
||||
|
||||
mdss_rgb_write_command(rgb_data, MIPI_DCS_SET_DISPLAY_ON); |
||||
msleep(30); |
||||
|
||||
pr_debug("%s: RGB panel power on done\n", __func__); |
||||
return 0; |
||||
} |
||||
|
||||
static int mdss_rgb_panel_off(struct mdss_panel_data *pdata) |
||||
{ |
||||
struct mdss_rgb_data *rgb_data = NULL; |
||||
|
||||
if (pdata == NULL) { |
||||
pr_err("%s: Invalid mdss panel data\n", __func__); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
rgb_data = container_of(pdata, struct mdss_rgb_data, |
||||
panel_data); |
||||
|
||||
mdss_rgb_write_command(rgb_data, MIPI_DCS_SET_DISPLAY_OFF); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int mdss_rgb_panel_timing_from_dt(struct device_node *np, |
||||
struct mdss_panel_timing *pt, |
||||
struct mdss_panel_data *panel_data) |
||||
{ |
||||
u64 tmp64; |
||||
int rc; |
||||
struct mdss_panel_info *pinfo; |
||||
|
||||
pinfo = &panel_data->panel_info; |
||||
|
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-panel-width", &pt->xres); |
||||
if (rc) { |
||||
pr_err("%s:%d, panel width not specified\n", |
||||
__func__, __LINE__); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-panel-height", &pt->yres); |
||||
if (rc) { |
||||
pr_err("%s:%d, panel height not specified\n", |
||||
__func__, __LINE__); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
pt->h_front_porch = 6; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-h-front-porch", |
||||
&pt->h_front_porch); |
||||
|
||||
pt->h_back_porch = 6; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-h-back-porch", |
||||
&pt->h_back_porch); |
||||
|
||||
pt->h_pulse_width = 2; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-h-pulse-width", |
||||
&pt->h_pulse_width); |
||||
|
||||
pt->hsync_skew = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-h-sync-skew", |
||||
&pt->hsync_skew); |
||||
|
||||
pt->v_back_porch = 6; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-v-back-porch", |
||||
&pt->v_back_porch); |
||||
|
||||
pt->v_front_porch = 6; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-v-front-porch", |
||||
&pt->v_front_porch); |
||||
|
||||
pt->v_pulse_width = 2; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-v-pulse-width", |
||||
&pt->v_pulse_width); |
||||
|
||||
pt->border_left = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-h-left-border", |
||||
&pt->border_left); |
||||
|
||||
pt->border_right = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-h-right-border", |
||||
&pt->border_right); |
||||
|
||||
pt->border_top = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-v-top-border", |
||||
&pt->border_top); |
||||
|
||||
pt->border_bottom = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-v-bottom-border", |
||||
&pt->border_bottom); |
||||
|
||||
pt->frame_rate = DEFAULT_FRAME_RATE; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-panel-framerate", |
||||
(u32 *)&pt->frame_rate); |
||||
|
||||
rc = of_property_read_u64(np, "qcom,mdss-rgb-panel-clockrate", &tmp64); |
||||
if (rc == -EOVERFLOW) { |
||||
tmp64 = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-panel-clockrate", |
||||
(u32 *)&tmp64); |
||||
} |
||||
pt->clk_rate = !rc ? tmp64 : 0; |
||||
|
||||
pt->name = kstrdup(np->name, GFP_KERNEL); |
||||
pr_debug("%s: found new timing \"%s\"\n", __func__, np->name); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int mdss_rgb_clk_refresh(struct mdss_rgb_data *rgb_data) |
||||
{ |
||||
struct mdss_panel_info *pinfo = NULL; |
||||
struct mdss_panel_data *pdata = &rgb_data->panel_data; |
||||
int rc = 0; |
||||
|
||||
if (!pdata) { |
||||
pr_err("%s: invalid mdss panel data\n", __func__); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
pinfo = &pdata->panel_info; |
||||
|
||||
mdss_rgb_clk_div_config(rgb_data, &pdata->panel_info, |
||||
pdata->panel_info.mipi.frame_rate); |
||||
|
||||
rgb_data->refresh_clk_rate = false; |
||||
rgb_data->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; |
||||
rgb_data->byte_clk_rate = pdata->panel_info.clk_rate / 8; |
||||
pr_debug("%s rgb_data->byte_clk_rate=%d rgb_data->pclk_rate=%d\n", |
||||
__func__, rgb_data->byte_clk_rate, rgb_data->pclk_rate); |
||||
|
||||
rc = mdss_dsi_clk_set_link_rate(rgb_data->clk_handle, |
||||
MDSS_DSI_LINK_BYTE_CLK, rgb_data->byte_clk_rate, |
||||
MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); |
||||
if (rc) { |
||||
pr_err("%s: byte_clk - clk_set_rate failed\n", |
||||
__func__); |
||||
return rc; |
||||
} |
||||
|
||||
rc = mdss_dsi_clk_set_link_rate(rgb_data->clk_handle, |
||||
MDSS_DSI_LINK_PIX_CLK, rgb_data->pclk_rate, |
||||
MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); |
||||
if (rc) |
||||
pr_err("%s: pixel_clk - clk_set_rate failed\n", |
||||
__func__); |
||||
return rc; |
||||
} |
||||
|
||||
int mdss_rgb_panel_timing_switch(struct mdss_rgb_data *rgb_data, |
||||
struct mdss_panel_timing *timing) |
||||
{ |
||||
struct mdss_panel_info *pinfo = &rgb_data->panel_data.panel_info; |
||||
struct mdss_panel_data *panel_data = &rgb_data->panel_data; |
||||
|
||||
if (!timing) |
||||
return -EINVAL; |
||||
|
||||
if (timing == panel_data->current_timing) { |
||||
pr_warn("%s: panel timing \"%s\" already set\n", __func__, |
||||
timing->name); |
||||
return 0; /* nothing to do */ |
||||
} |
||||
|
||||
//Copy Timings from display_timing struct to panel_info struct
|
||||
mdss_panel_info_from_timing(timing, pinfo); |
||||
|
||||
panel_data->current_timing = timing; |
||||
if (!timing->clk_rate) |
||||
rgb_data->refresh_clk_rate = true; |
||||
|
||||
mdss_rgb_clk_refresh(rgb_data); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
static int mdss_rgb_panel_parse_display_timings(struct device_node *np, |
||||
struct mdss_rgb_data *rgb_data) |
||||
{ |
||||
struct device_node *timings_np; |
||||
struct mdss_panel_data *panel_data = &rgb_data->panel_data; |
||||
int rc = 0; |
||||
|
||||
INIT_LIST_HEAD(&panel_data->timings_list); |
||||
|
||||
timings_np = of_get_child_by_name(np, "qcom,mdss-rgb-display-timings"); |
||||
|
||||
if (!timings_np) { |
||||
/*
|
||||
* display timings node is not available, fallback to reading |
||||
* timings directly from root node instead |
||||
*/ |
||||
struct mdss_panel_timing pt; |
||||
|
||||
memset(&pt, 0, sizeof(struct mdss_panel_timing)); |
||||
|
||||
pr_debug("reading display-timings from panel node\n"); |
||||
rc = mdss_rgb_panel_timing_from_dt(np, &pt, panel_data); |
||||
if (!rc) { |
||||
/*
|
||||
* Switch to the parsed timings |
||||
*/ |
||||
rc = mdss_rgb_panel_timing_switch(rgb_data, &pt); |
||||
} |
||||
} |
||||
|
||||
return rc; |
||||
} |
||||
|
||||
static int mdss_rgb_panel_parse_dt(struct device_node *np, |
||||
struct mdss_rgb_data *rgb_data) |
||||
{ |
||||
int rc = 0; |
||||
struct mdss_panel_info *pinfo = &(rgb_data->panel_data.panel_info); |
||||
|
||||
pinfo->physical_width = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-pan-physical-width-dimension", |
||||
&pinfo->physical_width); |
||||
|
||||
pinfo->physical_height = 0; |
||||
rc = of_property_read_u32(np, "qcom,mdss-pan-physical-height-dimension", |
||||
&pinfo->physical_height); |
||||
|
||||
pinfo->bpp = 24; |
||||
rc = of_property_read_u32(np, "qcom,mdss-rgb-bpp", &pinfo->bpp); |
||||
if (rc) { |
||||
pr_err("%s:%d, bpp not specified\n", __func__, __LINE__); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
pinfo->mipi.mode = DSI_VIDEO_MODE; |
||||
|
||||
switch (pinfo->bpp) { |
||||
case 16: |
||||
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB565; |
||||
break; |
||||
case 18: |
||||
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB666; |
||||
break; |
||||
case 24: |
||||
default: |
||||
pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888; |
||||
break; |
||||
} |
||||
|
||||
rc = mdss_rgb_panel_parse_display_timings(np, rgb_data); |
||||
return rc; |
||||
} |
||||
|
||||
int mdss_rgb_panel_init(struct device_node *node, |
||||
struct mdss_rgb_data *rgb_data) |
||||
{ |
||||
int rc = 0; |
||||
static const char *panel_name; |
||||
struct mdss_panel_info *pinfo; |
||||
|
||||
if (!node) { |
||||
pr_err("%s: Invalid device node\n", __func__); |
||||
return -ENODEV; |
||||
} |
||||
|
||||
pinfo = &rgb_data->panel_data.panel_info; |
||||
|
||||
pinfo->panel_name[0] = '\0'; |
||||
panel_name = of_get_property(node, "qcom,mdss-rgb-panel-name", NULL); |
||||
if (!panel_name) { |
||||
pr_info("%s:%d, Panel name not specified\n", |
||||
__func__, __LINE__); |
||||
} else { |
||||
pr_info("%s: Panel Name = %s\n", __func__, panel_name); |
||||
strlcpy(&pinfo->panel_name[0], panel_name, |
||||
sizeof(pinfo->panel_name)); |
||||
} |
||||
|
||||
rc = mdss_rgb_panel_parse_dt(node, rgb_data); |
||||
if (rc) |
||||
return rc; |
||||
|
||||
rgb_data->on = mdss_rgb_panel_on; |
||||
rgb_data->off = mdss_rgb_panel_off; |
||||
return rc; |
||||
} |
Loading…
Reference in new issue