24 bit RGB per pixel. It provides a MIPI DSI interface to
the host and has a built-in LED backlight.
+config DRM_PANEL_JADARD_JD9365DA_H3
+ tristate "Jadard JD9365DA-H3 WUXGA DSI panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for Jadard JD9365DA-H3
+ WUXGA MIPI DSI panel. The panel support TFT dot matrix LCD with
+ 800RGBx1280 dots at maximum.
+
config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o
obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
+obj-$(CONFIG_DRM_PANEL_JADARD_JD9365DA_H3) += panel-jadard-jd9365da-h3.o
obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o
obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019 Radxa Limited
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ *
+ * Author:
+ * - Jagan Teki <jagan@amarulasolutions.com>
+ * - Stephen Chen <stephen@radxa.com>
+ */
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <video/display_timing.h>
+#include <video/videomode.h>
+
+#define DSI_DRIVER_NAME "starfive-dri"
+
+enum cmd_type {
+ CMD_TYPE_DCS,
+ CMD_TYPE_DELAY,
+};
+
+struct jadard_init_cmd {
+ enum cmd_type type;
+ const char *data;
+ size_t len;
+};
+
+#define _INIT_CMD_DCS(...) \
+ { \
+ .type = CMD_TYPE_DCS, \
+ .data = (char[]){__VA_ARGS__}, \
+ .len = sizeof((char[]){__VA_ARGS__}) \
+ } \
+
+#define _INIT_CMD_DELAY(...) \
+ { \
+ .type = CMD_TYPE_DELAY, \
+ .data = (char[]){__VA_ARGS__}, \
+ .len = sizeof((char[]){__VA_ARGS__}) \
+ } \
+
+struct jadard_panel_desc {
+ const struct drm_display_mode mode;
+ unsigned int lanes;
+ enum mipi_dsi_pixel_format format;
+ const struct jadard_init_cmd *init_cmds;
+ u32 num_init_cmds;
+ const struct display_timing *timings;
+ unsigned int num_timings;
+};
+
+struct jadard {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ const struct jadard_panel_desc *desc;
+ struct i2c_client *client;
+
+ struct device *dev;
+
+ struct regulator *vdd;
+ struct regulator *vccio;
+ struct gpio_desc *reset;
+ struct gpio_desc *enable;
+ bool enable_initialized;
+};
+
+static inline struct jadard *panel_to_jadard(struct drm_panel *panel)
+{
+ return container_of(panel, struct jadard, panel);
+}
+
+static int jadard_enable(struct drm_panel *panel)
+{
+ struct device *dev = panel->dev;
+ struct jadard *jadard = panel_to_jadard(panel);
+ const struct jadard_panel_desc *desc = jadard->desc;
+ struct mipi_dsi_device *dsi = jadard->dsi;
+ unsigned int i;
+ int err;
+ if (jadard->enable_initialized == true)
+ return 0;
+
+ for (i = 0; i < desc->num_init_cmds; i++) {
+ const struct jadard_init_cmd *cmd = &desc->init_cmds[i];
+
+ switch (cmd->type) {
+ case CMD_TYPE_DELAY:
+ msleep(cmd->data[0]);
+ err = 0;
+ break;
+ case CMD_TYPE_DCS:
+ err = mipi_dsi_dcs_write(dsi, cmd->data[0],
+ cmd->len <= 1 ? NULL : &cmd->data[1],
+ cmd->len - 1);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (err < 0) {
+ DRM_DEV_ERROR(dev, "failed to write CMD#0x%x\n", cmd->data[0]);
+ return err;
+ }
+
+ }
+
+ err = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (err < 0)
+ DRM_DEV_ERROR(dev, "failed to exit sleep mode ret = %d\n", err);
+ msleep(120);
+
+ err = mipi_dsi_dcs_set_display_on(dsi);
+ if (err < 0)
+ DRM_DEV_ERROR(dev, "failed to set display on ret = %d\n", err);
+ jadard->enable_initialized = true ;
+
+ return 0;
+}
+
+static int jadard_disable(struct drm_panel *panel)
+{
+ struct device *dev = panel->dev;
+ struct jadard *jadard = panel_to_jadard(panel);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_off(jadard->dsi);
+ if (ret < 0)
+ DRM_DEV_ERROR(dev, "failed to set display off: %d\n", ret);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(jadard->dsi);
+ if (ret < 0)
+ DRM_DEV_ERROR(dev, "failed to enter sleep mode: %d\n", ret);
+
+ jadard->enable_initialized = false;
+
+ return 0;
+}
+
+static int jadard_prepare(struct drm_panel *panel)
+{
+ struct device *dev = panel->dev;
+ struct jadard *jadard = panel_to_jadard(panel);
+ const struct jadard_panel_desc *desc = jadard->desc;
+ struct mipi_dsi_device *dsi = jadard->dsi;
+ unsigned int i;
+ int err;
+
+ if (jadard->enable_initialized == true)
+ return 0;
+
+ gpiod_direction_output(jadard->enable, 0);
+ gpiod_set_value(jadard->enable, 1);
+ mdelay(100);
+
+ gpiod_direction_output(jadard->reset, 0);
+ mdelay(100);
+ gpiod_set_value(jadard->reset, 1);
+ mdelay(100);
+ gpiod_set_value(jadard->reset, 0);
+ mdelay(100);
+ gpiod_set_value(jadard->reset, 1);
+ mdelay(150);
+
+ return 0;
+}
+
+static int jadard_unprepare(struct drm_panel *panel)
+{
+ struct jadard *jadard = panel_to_jadard(panel);
+
+ gpiod_set_value(jadard->reset, 1);
+ msleep(120);
+#if 0
+ regulator_disable(jadard->vdd);
+ regulator_disable(jadard->vccio);
+#endif
+ return 0;
+}
+
+static int jadard_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct jadard *jadard = panel_to_jadard(panel);
+ const struct drm_display_mode *desc_mode = &jadard->desc->mode;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, desc_mode);
+ if (!mode) {
+ DRM_DEV_ERROR(&jadard->dsi->dev, "failed to add mode %ux%ux@%u\n",
+ desc_mode->hdisplay, desc_mode->vdisplay,
+ drm_mode_vrefresh(desc_mode));
+ return -ENOMEM;
+ }
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+
+ return 1;
+}
+
+static int seiko_panel_get_timings(struct drm_panel *panel,
+ unsigned int num_timings,
+ struct display_timing *timings)
+{
+ struct jadard *jadard = panel_to_jadard(panel);
+ unsigned int i;
+
+ if (jadard->desc->num_timings < num_timings)
+ num_timings = jadard->desc->num_timings;
+
+ if (timings)
+ for (i = 0; i < num_timings; i++)
+ timings[i] = jadard->desc->timings[i];
+
+ return jadard->desc->num_timings;
+}
+
+static const struct drm_panel_funcs jadard_funcs = {
+ .disable = jadard_disable,
+ .unprepare = jadard_unprepare,
+ .prepare = jadard_prepare,
+ .enable = jadard_enable,
+ .get_modes = jadard_get_modes,
+ .get_timings = seiko_panel_get_timings,
+};
+
+static const struct jadard_init_cmd cz101b4001_init_cmds[] = {
+ _INIT_CMD_DCS(0x01),
+ _INIT_CMD_DELAY(100),
+ _INIT_CMD_DCS(0xE0, 0x00),
+ _INIT_CMD_DCS(0xE1, 0x93),
+ _INIT_CMD_DCS(0xE2, 0x65),
+ _INIT_CMD_DCS(0xE3, 0xF8),
+ _INIT_CMD_DCS(0x80, 0x03),
+ _INIT_CMD_DCS(0xE0, 0x01),
+ _INIT_CMD_DCS(0x00, 0x00),
+ _INIT_CMD_DCS(0x01, 0x7E),
+ _INIT_CMD_DCS(0x03, 0x00),
+ _INIT_CMD_DCS(0x04, 0x65),
+ _INIT_CMD_DCS(0x0C, 0x74),
+ _INIT_CMD_DCS(0x17, 0x00),
+ _INIT_CMD_DCS(0x18, 0xB7),
+ _INIT_CMD_DCS(0x19, 0x00),
+ _INIT_CMD_DCS(0x1A, 0x00),
+ _INIT_CMD_DCS(0x1B, 0xB7),
+ _INIT_CMD_DCS(0x1C, 0x00),
+ _INIT_CMD_DCS(0x24, 0xFE),
+ _INIT_CMD_DCS(0x37, 0x19),
+ _INIT_CMD_DCS(0x38, 0x05),
+ _INIT_CMD_DCS(0x39, 0x00),
+ _INIT_CMD_DCS(0x3A, 0x01),
+ _INIT_CMD_DCS(0x3B, 0x01),
+ _INIT_CMD_DCS(0x3C, 0x70),
+ _INIT_CMD_DCS(0x3D, 0xFF),
+ _INIT_CMD_DCS(0x3E, 0xFF),
+ _INIT_CMD_DCS(0x3F, 0xFF),
+ _INIT_CMD_DCS(0x40, 0x06),
+ _INIT_CMD_DCS(0x41, 0xA0),
+ _INIT_CMD_DCS(0x43, 0x1E),
+ _INIT_CMD_DCS(0x44, 0x0F),
+ _INIT_CMD_DCS(0x45, 0x28),
+ _INIT_CMD_DCS(0x4B, 0x04),
+ _INIT_CMD_DCS(0x55, 0x02),
+ _INIT_CMD_DCS(0x56, 0x01),
+ _INIT_CMD_DCS(0x57, 0xA9),
+ _INIT_CMD_DCS(0x58, 0x0A),
+ _INIT_CMD_DCS(0x59, 0x0A),
+ _INIT_CMD_DCS(0x5A, 0x37),
+ _INIT_CMD_DCS(0x5B, 0x19),
+ _INIT_CMD_DCS(0x5D, 0x78),
+ _INIT_CMD_DCS(0x5E, 0x63),
+ _INIT_CMD_DCS(0x5F, 0x54),
+ _INIT_CMD_DCS(0x60, 0x49),
+ _INIT_CMD_DCS(0x61, 0x45),
+ _INIT_CMD_DCS(0x62, 0x38),
+ _INIT_CMD_DCS(0x63, 0x3D),
+ _INIT_CMD_DCS(0x64, 0x28),
+ _INIT_CMD_DCS(0x65, 0x43),
+ _INIT_CMD_DCS(0x66, 0x41),
+ _INIT_CMD_DCS(0x67, 0x43),
+ _INIT_CMD_DCS(0x68, 0x62),
+ _INIT_CMD_DCS(0x69, 0x50),
+ _INIT_CMD_DCS(0x6A, 0x57),
+ _INIT_CMD_DCS(0x6B, 0x49),
+ _INIT_CMD_DCS(0x6C, 0x44),
+ _INIT_CMD_DCS(0x6D, 0x37),
+ _INIT_CMD_DCS(0x6E, 0x23),
+ _INIT_CMD_DCS(0x6F, 0x10),
+ _INIT_CMD_DCS(0x70, 0x78),
+ _INIT_CMD_DCS(0x71, 0x63),
+ _INIT_CMD_DCS(0x72, 0x54),
+ _INIT_CMD_DCS(0x73, 0x49),
+ _INIT_CMD_DCS(0x74, 0x45),
+ _INIT_CMD_DCS(0x75, 0x38),
+ _INIT_CMD_DCS(0x76, 0x3D),
+ _INIT_CMD_DCS(0x77, 0x28),
+ _INIT_CMD_DCS(0x78, 0x43),
+ _INIT_CMD_DCS(0x79, 0x41),
+ _INIT_CMD_DCS(0x7A, 0x43),
+ _INIT_CMD_DCS(0x7B, 0x62),
+ _INIT_CMD_DCS(0x7C, 0x50),
+ _INIT_CMD_DCS(0x7D, 0x57),
+ _INIT_CMD_DCS(0x7E, 0x49),
+ _INIT_CMD_DCS(0x7F, 0x44),
+ _INIT_CMD_DCS(0x80, 0x37),
+ _INIT_CMD_DCS(0x81, 0x23),
+ _INIT_CMD_DCS(0x82, 0x10),
+ _INIT_CMD_DCS(0xE0, 0x02),
+ _INIT_CMD_DCS(0x00, 0x47),
+ _INIT_CMD_DCS(0x01, 0x47),
+ _INIT_CMD_DCS(0x02, 0x45),
+ _INIT_CMD_DCS(0x03, 0x45),
+ _INIT_CMD_DCS(0x04, 0x4B),
+ _INIT_CMD_DCS(0x05, 0x4B),
+ _INIT_CMD_DCS(0x06, 0x49),
+ _INIT_CMD_DCS(0x07, 0x49),
+ _INIT_CMD_DCS(0x08, 0x41),
+ _INIT_CMD_DCS(0x09, 0x1F),
+ _INIT_CMD_DCS(0x0A, 0x1F),
+ _INIT_CMD_DCS(0x0B, 0x1F),
+ _INIT_CMD_DCS(0x0C, 0x1F),
+ _INIT_CMD_DCS(0x0D, 0x1F),
+ _INIT_CMD_DCS(0x0E, 0x1F),
+ _INIT_CMD_DCS(0x0F, 0x5F),
+ _INIT_CMD_DCS(0x10, 0x5F),
+ _INIT_CMD_DCS(0x11, 0x57),
+ _INIT_CMD_DCS(0x12, 0x77),
+ _INIT_CMD_DCS(0x13, 0x35),
+ _INIT_CMD_DCS(0x14, 0x1F),
+ _INIT_CMD_DCS(0x15, 0x1F),
+ _INIT_CMD_DCS(0x16, 0x46),
+ _INIT_CMD_DCS(0x17, 0x46),
+ _INIT_CMD_DCS(0x18, 0x44),
+ _INIT_CMD_DCS(0x19, 0x44),
+ _INIT_CMD_DCS(0x1A, 0x4A),
+ _INIT_CMD_DCS(0x1B, 0x4A),
+ _INIT_CMD_DCS(0x1C, 0x48),
+ _INIT_CMD_DCS(0x1D, 0x48),
+ _INIT_CMD_DCS(0x1E, 0x40),
+ _INIT_CMD_DCS(0x1F, 0x1F),
+ _INIT_CMD_DCS(0x20, 0x1F),
+ _INIT_CMD_DCS(0x21, 0x1F),
+ _INIT_CMD_DCS(0x22, 0x1F),
+ _INIT_CMD_DCS(0x23, 0x1F),
+ _INIT_CMD_DCS(0x24, 0x1F),
+ _INIT_CMD_DCS(0x25, 0x5F),
+ _INIT_CMD_DCS(0x26, 0x5F),
+ _INIT_CMD_DCS(0x27, 0x57),
+ _INIT_CMD_DCS(0x28, 0x77),
+ _INIT_CMD_DCS(0x29, 0x35),
+ _INIT_CMD_DCS(0x2A, 0x1F),
+ _INIT_CMD_DCS(0x2B, 0x1F),
+ _INIT_CMD_DCS(0x58, 0x40),
+ _INIT_CMD_DCS(0x59, 0x00),
+ _INIT_CMD_DCS(0x5A, 0x00),
+ _INIT_CMD_DCS(0x5B, 0x10),
+ _INIT_CMD_DCS(0x5C, 0x06),
+ _INIT_CMD_DCS(0x5D, 0x40),
+ _INIT_CMD_DCS(0x5E, 0x01),
+ _INIT_CMD_DCS(0x5F, 0x02),
+ _INIT_CMD_DCS(0x60, 0x30),
+ _INIT_CMD_DCS(0x61, 0x01),
+ _INIT_CMD_DCS(0x62, 0x02),
+ _INIT_CMD_DCS(0x63, 0x03),
+ _INIT_CMD_DCS(0x64, 0x6B),
+ _INIT_CMD_DCS(0x65, 0x05),
+ _INIT_CMD_DCS(0x66, 0x0C),
+ _INIT_CMD_DCS(0x67, 0x73),
+ _INIT_CMD_DCS(0x68, 0x09),
+ _INIT_CMD_DCS(0x69, 0x03),
+ _INIT_CMD_DCS(0x6A, 0x56),
+ _INIT_CMD_DCS(0x6B, 0x08),
+ _INIT_CMD_DCS(0x6C, 0x00),
+ _INIT_CMD_DCS(0x6D, 0x04),
+ _INIT_CMD_DCS(0x6E, 0x04),
+ _INIT_CMD_DCS(0x6F, 0x88),
+ _INIT_CMD_DCS(0x70, 0x00),
+ _INIT_CMD_DCS(0x71, 0x00),
+ _INIT_CMD_DCS(0x72, 0x06),
+ _INIT_CMD_DCS(0x73, 0x7B),
+ _INIT_CMD_DCS(0x74, 0x00),
+ _INIT_CMD_DCS(0x75, 0xF8),
+ _INIT_CMD_DCS(0x76, 0x00),
+ _INIT_CMD_DCS(0x77, 0xD5),
+ _INIT_CMD_DCS(0x78, 0x2E),
+ _INIT_CMD_DCS(0x79, 0x12),
+ _INIT_CMD_DCS(0x7A, 0x03),
+ _INIT_CMD_DCS(0x7B, 0x00),
+ _INIT_CMD_DCS(0x7C, 0x00),
+ _INIT_CMD_DCS(0x7D, 0x03),
+ _INIT_CMD_DCS(0x7E, 0x7B),
+ _INIT_CMD_DCS(0xE0, 0x04),
+ _INIT_CMD_DCS(0x00, 0x0E),
+ _INIT_CMD_DCS(0x02, 0xB3),
+ _INIT_CMD_DCS(0x09, 0x60),
+ _INIT_CMD_DCS(0x0E, 0x2A),
+ _INIT_CMD_DCS(0x36, 0x59),
+ _INIT_CMD_DCS(0xE0, 0x00),
+
+ _INIT_CMD_DELAY(120),
+};
+
+static const struct display_timing jadard_timing = {
+ .pixelclock = { 79200000, 79200000, 79200000 },
+ .hactive = { 800, 800, 800 },
+ .hfront_porch = { 356, 356, 356 },
+ .hback_porch = { 134, 134, 134 },
+ .hsync_len = { 7, 7, 7 },
+ .vactive = { 1280, 1280, 1280 },
+ .vfront_porch = { 84, 84, 84 },
+ .vback_porch = { 20, 20, 20 },
+ .vsync_len = { 9, 9, 9 },
+ .flags = DISPLAY_FLAGS_DE_LOW,
+};
+
+static const struct jadard_panel_desc cz101b4001_desc = {
+ .mode = {
+ .clock = 79200,
+
+ .hdisplay = 800,
+ .hsync_start = 800 + 139,
+ .hsync_end = 800 + 139 + 5,
+ .htotal = 800 + 139 + 5 + 5,
+
+ .vdisplay = 1280,
+ .vsync_start = 1280 + 84,
+ .vsync_end = 1280 + 84 + 20,
+ .vtotal = 1280 + 84+ 20 + 7,
+
+ .width_mm = 62,
+ .height_mm = 110,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ },
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .init_cmds = cz101b4001_init_cmds,
+ .num_init_cmds = ARRAY_SIZE(cz101b4001_init_cmds),
+ .timings = &jadard_timing,
+ .num_timings = 1,
+};
+
+static int panel_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ u8 reg_value = 0;
+ struct jadard *jd_panel;
+ const struct jadard_panel_desc *desc;
+
+ struct device_node *endpoint, *dsi_host_node;
+ struct mipi_dsi_host *host;
+ struct device *dev = &client->dev;
+
+ struct mipi_dsi_device_info info = {
+ .type = DSI_DRIVER_NAME,
+ .channel = 1, //0,
+ .node = NULL,
+ };
+
+ jd_panel = devm_kzalloc(&client->dev, sizeof(struct jadard), GFP_KERNEL);
+ if (!jd_panel )
+ return -ENOMEM;
+ desc = of_device_get_match_data(dev);
+
+ jd_panel ->client = client;
+ i2c_set_clientdata(client, jd_panel);
+
+ jd_panel->enable_initialized = false;
+
+ jd_panel->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(jd_panel->reset)) {
+ DRM_DEV_ERROR(dev, "failed to get our reset GPIO\n");
+ return PTR_ERR(jd_panel->reset);
+ }
+
+ jd_panel->enable = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(jd_panel->enable)) {
+ DRM_DEV_ERROR(dev, "failed to get our enable GPIO\n");
+ return PTR_ERR(jd_panel->enable);
+ }
+
+ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!endpoint)
+ return -ENODEV;
+
+ dsi_host_node = of_graph_get_remote_port_parent(endpoint);
+ if (!dsi_host_node)
+ goto error;
+
+ host = of_find_mipi_dsi_host_by_node(dsi_host_node);
+ of_node_put(dsi_host_node);
+ if (!host) {
+ of_node_put(endpoint);
+ return -EPROBE_DEFER;
+ }
+
+ drm_panel_init(&jd_panel->panel, dev, &jadard_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ drm_panel_add(&jd_panel->panel);
+
+ info.node = of_node_get(of_graph_get_remote_port(endpoint));
+ if (!info.node)
+ goto error;
+
+ of_node_put(endpoint);
+ jd_panel->desc = desc;
+
+ jd_panel->dsi = mipi_dsi_device_register_full(host, &info);
+ if (IS_ERR(jd_panel->dsi)) {
+ dev_err(dev, "DSI device registration failed: %ld\n",
+ PTR_ERR(jd_panel->dsi));
+ return PTR_ERR(jd_panel->dsi);
+ }
+
+ mipi_dsi_set_drvdata(jd_panel->dsi, jd_panel);
+
+ return 0;
+error:
+ of_node_put(endpoint);
+ return -ENODEV;
+no_panel:
+ mipi_dsi_device_unregister(jd_panel->dsi);
+ //drm_panel_remove(&jd_panel->panel);
+ //mipi_dsi_detach(jd_panel->dsi);
+
+ return -ENODEV;
+
+
+}
+
+static int panel_remove(struct i2c_client *client)
+{
+ struct jadard *jd_panel = i2c_get_clientdata(client);
+
+ mipi_dsi_detach(jd_panel->dsi);
+ drm_panel_remove(&jd_panel->panel);
+ mipi_dsi_device_unregister(jd_panel->dsi);
+ return 0;
+}
+
+static const struct i2c_device_id panel_id[] = {
+ { "starfive_jadard", 0 },
+ { }
+};
+
+static const struct of_device_id panel_dt_ids[] = {
+ { .compatible = "starfive_jadard", .data = &cz101b4001_desc},
+ { /* sentinel */ }
+};
+
+static struct i2c_driver panel_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "starfive_jadard",
+ .of_match_table = panel_dt_ids,
+ },
+ .probe = panel_probe,
+ .remove = panel_remove,
+ .id_table = panel_id,
+};
+
+static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct jadard *jadard = mipi_dsi_get_drvdata(dsi);
+
+ int ret;
+
+ dsi->mode_flags = MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE ;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->lanes = 4;
+ dsi->channel = 1;
+ dsi->hs_rate = 490000000;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+static int jadard_dsi_remove(struct mipi_dsi_device *dsi)
+{
+ struct jadard *jadard = mipi_dsi_get_drvdata(dsi);
+
+ mipi_dsi_detach(dsi);
+ drm_panel_remove(&jadard->panel);
+
+ return 0;
+}
+
+static const struct of_device_id jadard_of_match[] = {
+ { .compatible = "starfive-dri-panel-1", .data = &cz101b4001_desc },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jadard_of_match);
+
+static struct mipi_dsi_driver jadard_mipi_driver = {
+ .probe = jadard_dsi_probe,
+ .remove = jadard_dsi_remove,
+ .driver.name = DSI_DRIVER_NAME,
+};
+//module_mipi_dsi_driver(jadard_driver);
+
+
+static int __init init_panel(void)
+{
+ int err;
+
+ mipi_dsi_driver_register(&jadard_mipi_driver);
+ err = i2c_add_driver(&panel_driver);
+
+ return err;
+
+}
+module_init(init_panel);
+
+static void __exit exit_panel(void)
+{
+ i2c_del_driver(&panel_driver);
+ mipi_dsi_driver_unregister(&jadard_mipi_driver);
+}
+module_exit(exit_panel);
+
+
+MODULE_AUTHOR("Jagan Teki <jagan@edgeble.ai>");
+MODULE_AUTHOR("Stephen Chen <stephen@radxa.com>");
+MODULE_DESCRIPTION("Jadard JD9365DA-H3 WUXGA DSI panel");
+MODULE_LICENSE("GPL");
+
bpp, DSI_HFP_FRAME_OVERHEAD);
//dpi to dsi transfer can not match , reconfig those parms for waveshare
//for taobao old mipi panel .should change here : hsa 36 , hbp 108, hfp 288
- if (mode->hdisplay == 800) {
+ if (mode->vdisplay == 1280) {
+ dsi_cfg->hsa = 45-DSI_HSA_FRAME_OVERHEAD;
+ dsi_cfg->hbp = 134-DSI_HBP_FRAME_OVERHEAD;
+ dsi_cfg->hfp = 356-DSI_HFP_FRAME_OVERHEAD;
+ }
+ if (mode->vdisplay == 480) {
dsi_cfg->hsa = 117-DSI_HSA_FRAME_OVERHEAD;
dsi_cfg->hbp = 115-DSI_HBP_FRAME_OVERHEAD;
dsi_cfg->hfp = 209-DSI_HFP_FRAME_OVERHEAD;
dpi_htotal = mode_valid_check ? mode->htotal : mode->crtc_htotal;
/* data rate was in bytes/sec, convert to bits/sec. */
- phy_cfg->hs_clk_rate = 750000000;
+ phy_cfg->hs_clk_rate = output->phy_opts.mipi_dphy.hs_clk_rate;
dsi_hfp_ext = adj_dsi_htotal - dsi_htotal;
dsi_cfg->hfp += dsi_hfp_ext;
if (ret)
return ret;
- phy_cfg->hs_clk_rate = 750000000;
+ //phy_cfg->hs_clk_rate = output->phy_opts.mipi_dphy.hs_clk_rate;
+ if (mode->vdisplay == 480)
+ phy_cfg->hs_clk_rate = 750000000;
+ else if (mode->vdisplay == 1280)
+ phy_cfg->hs_clk_rate = 490000000;
+
+ dsi_cfg->htotal = dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD +
+ dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD +
+ dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD + dsi_cfg->hact;
dsi_hss_hsa_hse_hbp = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
* Power all internal DPHY blocks down and maintain their reset line
* asserted before changing the DPHY config.
*/
- writel(DPHY_CMN_PSO | DPHY_PLL_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN |
- DPHY_CMN_PDN | DPHY_PLL_PDN,
- dsi->regs + MCTL_DPHY_CFG0);
+ //writel(DPHY_CMN_PSO | DPHY_PLL_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN |
+ // DPHY_CMN_PDN | DPHY_PLL_PDN,
+ // dsi->regs + MCTL_DPHY_CFG0);
+ // Commented by Tony Ren: this is not appliable for our case as it is intended for its own dphy
phy_init(dsi->dphy);
phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
phy_power_on(dsi->dphy);
ret = sys_mipi_dsi_set_ppi_txbyte_hs(1, dsi);
-
+#if 0
writel(PLL_LOCKED, dsi->regs + MCTL_MAIN_STS_CLR);
writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN,
dsi->regs + MCTL_DPHY_CFG0);
writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN |
DPHY_D_RSTB(output->dev->lanes) | DPHY_C_RSTB,
dsi->regs + MCTL_DPHY_CFG0);
-
+#endif
/*
dpi_fifo_int = readl(dsi->regs + DPI_IRQ_CLR);
if (dpi_fifo_int)
static void cdns_dsi_init_link(struct cdns_dsi *dsi)
{
struct cdns_dsi_output *output = &dsi->output;
- unsigned long sysclk_period, ulpout;
+ unsigned long ulpout;
u32 val;
int i;
writel(val, dsi->regs + MCTL_MAIN_PHY_CTL);
- /* ULPOUT should be set to 1ms and is expressed in sysclk cycles.*/
- sysclk_period = NSEC_PER_SEC / clk_get_rate(dsi->dsi_sys_clk);
- ulpout = DIV_ROUND_UP(NSEC_PER_MSEC, sysclk_period);
+ ulpout = DIV_ROUND_UP(clk_get_rate(dsi->dsi_sys_clk), MSEC_PER_SEC);
+
writel(CLK_LANE_ULPOUT_TIME(ulpout) | DATA_LANE_ULPOUT_TIME(ulpout),
dsi->regs + MCTL_ULPOUT_TIME);
writel(LINK_EN, dsi->regs + MCTL_MAIN_DATA_CTL);
- val = CLK_LANE_EN | PLL_START;
+ val = CLK_LANE_EN | CLK_FORCE_STOP ; // | PLL_START; unused bit
for (i = 0; i < output->dev->lanes; i++)
val |= DATA_LANE_START(i);
writel(val, dsi->regs + MCTL_MAIN_EN);
+ udelay(20);
dsi->link_initialized = true;
}
+static void start_clane_hs(struct cdns_dsi *dsi)
+{
+ // struct cdns_dsi *dsi = (struct cdns_dsi *)handle->priv;
+ struct cdns_dsi_output *output = &dsi->output;
+
+ unsigned long ulpout;
+ u32 val;
+ int i;
+
+ val = WAIT_BURST_TIME(0xf);
+ for (i = 1; i < output->dev->lanes; i++)
+ val |= DATA_LANE_EN(i);
+
+ if (!(output->dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+ val |= CLK_CONTINUOUS;
+
+ writel(val, dsi->regs + MCTL_MAIN_PHY_CTL);
+
+ ulpout = DIV_ROUND_UP(clk_get_rate(dsi->dsi_sys_clk), MSEC_PER_SEC);
+ writel(CLK_LANE_ULPOUT_TIME(ulpout) | DATA_LANE_ULPOUT_TIME(ulpout),
+ dsi->regs + MCTL_ULPOUT_TIME);
+
+ writel(LINK_EN, dsi->regs + MCTL_MAIN_DATA_CTL);
+
+ val = CLK_LANE_EN; // | CLK_FORCE_STOP; // | PLL_START; unused bit
+ for (i = 0; i < output->dev->lanes; i++)
+ val |= DATA_LANE_START(i);
+
+ writel(val, dsi->regs + MCTL_MAIN_EN); // start hs clk lane
+
+ // clane output DDR(Double Data Rate) clock = half of dphy hs_rate, because hs is double edge sampling
+
+ dsi->link_initialized = true;
+}
+
static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
{
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
//WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));//original //7110 mode illegal,need confirm //cannot disable
cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false);
-
cdns_dsi_hs_init(dsi);
cdns_dsi_init_link(dsi);
+ if (output->panel)
+ drm_panel_prepare(output->panel);
+
+ if (output->panel)
+ drm_panel_enable(output->panel);
+
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
dsi->regs + VID_HSIZE1);
writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
phy_cfg->hs_clk_rate);
reg_wakeup = (phy_cfg->hs_prepare + phy_cfg->hs_zero) / tx_byte_period;
+
writel(REG_WAKEUP_TIME(reg_wakeup) | REG_LINE_DURATION(tmp),
dsi->regs + VID_DPHY_TIME);
- vrefresh = drm_mode_vrefresh(mode);//display_timing_vrefresh(dpi);
+ vrefresh = drm_mode_vrefresh(mode)-1;//display_timing_vrefresh(dpi);
tmp = NSEC_PER_SEC / vrefresh;
tmp /= tx_byte_period;
writel(tmp, dsi->regs + VID_MAIN_CTL);
}
+ //to restart the clane and dlane
+ start_clane_hs(dsi);
+
tmp = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
tmp &= ~(IF_VID_SELECT_MASK | HOST_EOT_GEN | IF_VID_MODE);
tmp = readl(dsi->regs + MCTL_MAIN_EN) | IF_EN(input->id);
writel(tmp, dsi->regs + MCTL_MAIN_EN);
+
}
static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
*/
np = of_graph_get_remote_node(dsi->base.dev->of_node, DSI_OUTPUT_PORT,
dev->channel);
+
if (!np)
np = of_node_get(dev->dev.of_node);
return ret;
}
+
+
static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
struct cdns_dsi *dsi = to_cdns_dsi(host);
- u32 cmd, val, wait = WRITE_COMPLETED, ctl = 0;
+ u32 cmd, sts, val, wait = WRITE_COMPLETED, ctl = 0;
struct mipi_dsi_packet packet;
int ret, i, tx_len, rx_len;
- u32 stat = 0;
- int timeout = 100;
- int stat_88;
- int stat_188;
- int stat_88_ack_val;
- ret = pm_runtime_get_sync(host->dev);
+ ret = pm_runtime_resume_and_get(host->dev);
if (ret < 0)
return ret;
/* For read operations, the maximum TX len is 2. */
if (rx_len && tx_len > 2) {
- ret = -EOPNOTSUPP;
+ ret = -ENOTSUPP;
goto out;
}
/* TX len is limited by the CMD FIFO depth. */
if (tx_len > dsi->direct_cmd_fifo_depth) {
- ret = -EOPNOTSUPP;
+ ret = -ENOTSUPP;
goto out;
}
/* RX len is limited by the RX FIFO depth. */
if (rx_len > dsi->rx_fifo_depth) {
- ret = -EOPNOTSUPP;
+ ret = -ENOTSUPP;
goto out;
}
ctl = BTA_EN;
}
- /* Clear status flags before sending the command. */
+ writel(readl(dsi->regs + MCTL_MAIN_DATA_CTL) | ctl,
+ dsi->regs + MCTL_MAIN_DATA_CTL);
- iowrite32(wait, dsi->regs + DIRECT_CMD_STS_CLR);
- iowrite32(wait, dsi->regs + DIRECT_CMD_STS_CTL);
- iowrite32(cmd, dsi->regs + DIRECT_CMD_MAIN_SETTINGS);
+ writel(cmd, dsi->regs + DIRECT_CMD_MAIN_SETTINGS);
for (i = 0; i < tx_len; i += 4) {
const u8 *buf = msg->tx_buf;
val = 0;
for (j = 0; j < 4 && j + i < tx_len; j++)
val |= (u32)buf[i + j] << (8 * j);
- iowrite32(val, dsi->regs + DIRECT_CMD_WRDATA);
+
+ writel(val, dsi->regs + DIRECT_CMD_WRDATA);
}
- iowrite32(0, dsi->regs + DIRECT_CMD_SEND);
- do {
- stat = readl(dsi->regs + DIRECT_CMD_STS);
- if ((stat & 0x02) == 0x02)
- break;
- mdelay(10);
- } while (--timeout);
- if (!timeout)
- DRM_DEBUG("timeout!\n");
+ /* Clear status flags before sending the command. */
+ writel(wait, dsi->regs + DIRECT_CMD_STS_CLR);
+ writel(wait, dsi->regs + DIRECT_CMD_STS_CTL);
+ reinit_completion(&dsi->direct_cmd_comp);
+ writel(0, dsi->regs + DIRECT_CMD_SEND);
+
+ wait_for_completion_timeout(&dsi->direct_cmd_comp,
+ msecs_to_jiffies(1000));
- stat_88 = readl(dsi->regs + DIRECT_CMD_STS);
- stat_188 = readl(dsi->regs + MCTL_DPHY_ERR_FLAG);
- stat_88_ack_val = stat_88 >> 16;
- if (stat_188 || stat_88_ack_val)
- dev_dbg(host->dev, "stat: [188h] %08x, [88h] %08x\r\n", stat_188, stat_88);
+ sts = readl(dsi->regs + DIRECT_CMD_STS);
+ writel(wait, dsi->regs + DIRECT_CMD_STS_CLR);
+ writel(0, dsi->regs + DIRECT_CMD_STS_CTL);
+
+ writel(readl(dsi->regs + MCTL_MAIN_DATA_CTL) & ~ctl,
+ dsi->regs + MCTL_MAIN_DATA_CTL);
+
+ /* We did not receive the events we were waiting for. */
+ if (!(sts & wait)) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ /* 'READ' or 'WRITE with ACK' failed. */
+ if (sts & (READ_COMPLETED_WITH_ERR | ACK_WITH_ERR_RCVD)) {
+ ret = -EIO;
+ goto out;
+ }
+
+ for (i = 0; i < rx_len; i += 4) {
+ u8 *buf = msg->rx_buf;
+ int j;
+
+ val = readl(dsi->regs + DIRECT_CMD_RDDATA);
+ for (j = 0; j < 4 && j + i < rx_len; j++)
+ buf[i + j] = val >> (8 * j);
+ }
out:
pm_runtime_put(host->dev);
static int __maybe_unused cdns_dsi_resume(struct device *dev)
{
- struct cdns_dsi *dsi = dev_get_drvdata(dev);
-
- reset_control_deassert(dsi->dsi_p_rst);
- clk_prepare_enable(dsi->dsi_p_clk);
- clk_prepare_enable(dsi->dsi_sys_clk);
-
return 0;
}
{
struct cdns_dsi *dsi = dev_get_drvdata(dev);
- clk_disable_unprepare(dsi->dsi_sys_clk);
- clk_disable_unprepare(dsi->dsi_p_clk);
- reset_control_assert(dsi->dsi_p_rst);
dsi->link_initialized = false;
return 0;
}
static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume,
NULL);
-#if 0
-static int cdns_dsi_drm_remove(struct platform_device *pdev)
-{
- struct cdns_dsi *dsi = platform_get_drvdata(pdev);
-
- mipi_dsi_host_unregister(&dsi->base);
- pm_runtime_disable(&pdev->dev);
-
- return 0;
-}
-#endif
-
-static const struct of_device_id cdns_dsi_of_match[] = {
- { .compatible = "cdns,dsi" },
- { },
-};
static int cdns_check_register_access(struct cdns_dsi* dsi)
{
return 0;
}
-static int starfive_dsi_bind(struct device *dev, struct device *master, void *data)
+static int cdns_dsi_drm_probe(struct platform_device *pdev)
{
struct cdns_dsi *dsi;
struct cdns_dsi_input *input;
struct resource *res;
- struct platform_device *pdev = to_platform_device(dev);
- //struct drm_device *drm_dev = data;
- //struct starfive_drm_private *private = drm_dev->dev_private;
- int ret;
- int irq;
+ int ret, irq;
u32 val;
dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
return -ENOMEM;
platform_set_drvdata(pdev, dsi);
+
input = &dsi->input;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (IS_ERR(dsi->regs))
return PTR_ERR(dsi->regs);
- ret = cdns_dsi_get_clock(dev, dsi);//get clock res
-
- dev_info(dev, "dsi_sys_clk = %ld\n",clk_get_rate(dsi->dsi_sys_clk));
+ ret = cdns_dsi_get_clock(&pdev->dev, dsi);//get clock res
- ret = cdns_dsi_get_reset(dev, dsi);//get reset res
+ ret = cdns_dsi_get_reset(&pdev->dev, dsi);//get reset res
- ret = cdns_dsi_clock_enable(dsi, dev);
+ ret = cdns_dsi_clock_enable(dsi, &pdev->dev);
if (ret) {
- dev_err(dev, "failed to enable clock\n");
+ dev_err(&pdev->dev, "failed to enable clock\n");
return ret;
}
- ret = cdns_dsi_resets_deassert(dsi, dev);
+ ret = cdns_dsi_resets_deassert(dsi, &pdev->dev);
if (ret < 0) {
- dev_err(dev, "failed to deassert reset\n");
+ dev_err(&pdev->dev, "failed to deassert reset\n");
return ret;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0){
- dev_err(dev, "---get irq error\n");
+ dev_err(&pdev->dev, "---get irq error\n");
return irq;
}
ret = cdns_check_register_access(dsi);
if (ret) {
- dev_err(dev, "error: r/w test generic reg failed\n");
+ dev_err(&pdev->dev, "error: r/w test generic reg failed\n");
goto ERROR;
}
ret = devm_request_irq(&pdev->dev, irq, cdns_dsi_interrupt, 0,
dev_name(&pdev->dev), dsi);
- if (ret){
- dev_err(dev, "---devm_request_irq error\n");
- goto err_disable_pclk;
+ if (ret){
+ goto err_disable_pclk;
}
pm_runtime_enable(&pdev->dev);
if (ret)
goto err_disable_runtime_pm;
- init_seeed_panel();
- dev_err(dev, "====starfive_dsi_bind end\n");
return 0;
err_disable_runtime_pm:
return ret;
}
-static void starfive_dsi_unbind(struct device *dev, struct device *master, void *data)
+static int cdns_dsi_drm_remove(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct cdns_dsi *dsi = platform_get_drvdata(pdev);
int ret;
- ret = cdns_dsi_resets_assert(dsi, dev);
+ ret = cdns_dsi_resets_assert(dsi, &pdev->dev);
if (ret < 0)
- dev_err(dev, "failed to assert reset\n");
+ dev_err(&pdev->dev, "failed to assert reset\n");
cdns_dsi_clock_disable(dsi);
- exit_seeed_panel();
+ //exit_seeed_panel();
mipi_dsi_host_unregister(&dsi->base);
- pm_runtime_disable(dev);
-}
-
-static const struct component_ops starfive_dsi_component_ops = {
- .bind = starfive_dsi_bind,
- .unbind = starfive_dsi_unbind,
-};
-
-static int starfive_dsi_probe(struct platform_device *pdev)
-{
- return component_add(&pdev->dev, &starfive_dsi_component_ops);
-}
+ pm_runtime_disable(&pdev->dev);
-static int starfive_dsi_remove(struct platform_device *pdev)
-{
- component_del(&pdev->dev, &starfive_dsi_component_ops);
return 0;
}
-struct platform_driver starfive_dsi_platform_driver = {
- .probe = starfive_dsi_probe,
- .remove = starfive_dsi_remove,
+static const struct of_device_id cdns_dsi_of_match[] = {
+ { .compatible = "cdns,dsi" },
+ { },
+};
+
+static struct platform_driver cdns_dsi_platform_driver = {
+ .probe = cdns_dsi_drm_probe,
+ .remove = cdns_dsi_drm_remove,
.driver = {
.name = "cdns-dsi",
.of_match_table = cdns_dsi_of_match,
.pm = &cdns_dsi_pm_ops,
},
};
+module_platform_driver(cdns_dsi_platform_driver);
+
MODULE_AUTHOR("Boris Brezillon <boris.brezillon@bootlin.com>");
MODULE_DESCRIPTION("Cadence DSI driver");
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_panel.h>
#include "vs_drv.h"
-#define RPI_DSI_DRIVER_NAME "cdns-dri-panel"
+#define RPI_DSI_DRIVER_NAME "starfive-dri-panel"
/* I2C registers of the Atmel microcontroller. */
enum REG_ADDR {
MIPI_DSI_MODE_LPM);
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->lanes = 1;
+ dsi->hs_rate = 750000000;
ret = mipi_dsi_attach(dsi);
if (ret)
.probe = seeed_dsi_probe,
};
-int init_seeed_panel(void)
+static int __init init_seeed_panel(void)
{
int err;
err = i2c_add_driver(&seeed_panel_driver);
return err;
}
-EXPORT_SYMBOL(init_seeed_panel);
+module_init(init_seeed_panel);
-void exit_seeed_panel(void)
+static void __exit exit_seeed_panel(void)
{
i2c_del_driver(&seeed_panel_driver);
mipi_dsi_driver_unregister(&seeed_dsi_driver);
}
-EXPORT_SYMBOL(exit_seeed_panel);
+module_exit(exit_seeed_panel);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver");
+MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("A driver for seeed_panel");
-MODULE_LICENSE("GPL");
static int vs_crtc_enable_vblank(struct drm_crtc *crtc)
{
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
- struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(crtc->state);
+ //struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(crtc->state);
vs_crtc->funcs->enable_vblank(vs_crtc->dev, true);
struct device *dev = vs_crtc->dev;
struct drm_property_blob *blob = crtc->state->gamma_lut;
struct drm_color_lut *lut;
- struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(crtc->state);
+ //struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(crtc->state);
if (crtc_state->color_mgmt_changed) {
if ((blob) && (blob->length)) {
}
clk_set_parent(dc->dc8200_clk_pix1, dc->dc8200_pix0);
- udelay(1000);
dc_hw_set_out(&dc->hw, OUT_DPI, display.id);
} else {
if (dc->pix_clk_rate != mode->clock) {
clk_set_rate(dc->dc8200_pix0, mode->clock * 1000);
dc->pix_clk_rate = mode->clock;
}
-
clk_set_parent(dc->dc8200_clk_pix1, dc->dc8200_pix0);
clk_set_parent(dc->dc8200_clk_pix0, dc->hdmitx0_pixelclk);
dc_hw_set_out(&dc->hw, OUT_DP, display.id);
};
extern struct platform_driver dc_platform_driver;
-extern struct platform_driver starfive_dsi_platform_driver;
-extern int init_seeed_panel(void);
-extern void exit_seeed_panel(void);
+
#endif /* __VS_DC_H__ */
#ifdef CONFIG_STARFIVE_INNO_HDMI
&inno_hdmi_driver,
#endif
-#ifdef CONFIG_STARFIVE_DSI
- &starfive_dsi_platform_driver,
-#endif
&simple_encoder_driver,
extern struct platform_driver inno_hdmi_driver;
#endif
-#ifdef CONFIG_STARFIVE_DSI
-extern int init_seeed_panel(void);
-extern void exit_seeed_panel(void);
-extern struct platform_driver starfive_dsi_platform_driver;
-#endif
+
#endif /* __VS_DRV_H__ */
{25000000, 2400000000, 0x1, 0xC0, 0x000000, 0x0, 0x0D, 0x20, 0x16, 0x0A, 0x50, 0x15, 0x00, 0x18,},
{25000000, 2500000000, 0x1, 0xC8, 0x000000, 0x0, 0x0E, 0x21, 0x16, 0x0B, 0x53, 0x16, 0x00, 0x18,},
#elif (M31_DPHY_REFCLK == M31_DPHY_REFCLK_12M)
+ {12000000, 160000000, 0x0, 0x6a, 0xaa<<16|0xaa<<8|0xaa, 0x3, 0xa, 0x17, 0x11, 0x5, 0x2b, 0xd, 0x7, 0x3d,},
+ {12000000, 170000000, 0x0, 0x71, 0x55<<16|0x55<<8|0x55, 0x3, 0xb, 0x18, 0x11, 0x5, 0x2e, 0xd, 0x7, 0x3d,},
+ {12000000, 180000000, 0x0, 0x78, 0x0<<16|0x0<<8|0x0, 0x3, 0xb, 0x19, 0x12, 0x6, 0x30, 0xe, 0x7, 0x3e,},
+ {12000000, 190000000, 0x0, 0x7e, 0xaa<<16|0xaa<<8|0xaa, 0x3, 0xc, 0x1a, 0x12, 0x6, 0x33, 0xe, 0x7, 0x3e,},
+ {12000000, 200000000, 0x0, 0x85, 0x55<<16|0x55<<8|0x55, 0x3, 0xc, 0x1b, 0x13, 0x7, 0x35, 0xf, 0x7, 0x3f,},
+ {12000000, 320000000, 0x0, 0x6a, 0xaa<<16|0xaa<<8|0xaa, 0x2, 0x8, 0x14, 0xf, 0x5, 0x2b, 0xd, 0x3, 0x23,},
+ {12000000, 330000000, 0x0, 0x6e, 0x0<<16|0x0<<8|0x0, 0x2, 0x8, 0x15, 0xf, 0x5, 0x2d, 0xd, 0x3, 0x23,},
+ {12000000, 340000000, 0x0, 0x71, 0x55<<16|0x55<<8|0x55, 0x2, 0x9, 0x15, 0xf, 0x5, 0x2e, 0xd, 0x3, 0x23,},
+ {12000000, 350000000, 0x0, 0x74, 0xaa<<16|0xaa<<8|0xaa, 0x2, 0x9, 0x15, 0x10, 0x6, 0x2f, 0xe, 0x3, 0x24,},
+ {12000000, 360000000, 0x0, 0x78, 0x0<<16|0x0<<8|0x0, 0x2, 0x9, 0x16, 0x10, 0x6, 0x30, 0xe, 0x3, 0x24,},
+ {12000000, 370000000, 0x0, 0x7b, 0x55<<16|0x55<<8|0x55, 0x2, 0x9, 0x17, 0x10, 0x6, 0x32, 0xe, 0x3, 0x24,},
+ {12000000, 380000000, 0x0, 0x7e, 0xaa<<16|0xaa<<8|0xaa, 0x2, 0xa, 0x17, 0x10, 0x6, 0x33, 0xe, 0x3, 0x24,},
+ {12000000, 390000000, 0x0, 0x82, 0x0<<16|0x0<<8|0x0, 0x2, 0xa, 0x17, 0x11, 0x6, 0x35, 0xf, 0x3, 0x25,},
+ {12000000, 400000000, 0x0, 0x85, 0x55<<16|0x55<<8|0x55, 0x2, 0xa, 0x18, 0x11, 0x7, 0x35, 0xf, 0x3, 0x25,},
+ {12000000, 410000000, 0x0, 0x88, 0xaa<<16|0xaa<<8|0xaa, 0x2, 0xa, 0x19, 0x11, 0x7, 0x37, 0xf, 0x3, 0x25,},
+ {12000000, 420000000, 0x0, 0x8c, 0x0<<16|0x0<<8|0x0, 0x2, 0xa, 0x19, 0x12, 0x7, 0x38, 0x10, 0x3, 0x26,},
+ {12000000, 430000000, 0x0, 0x8f, 0x55<<16|0x55<<8|0x55, 0x2, 0xb, 0x19, 0x12, 0x7, 0x39, 0x10, 0x3, 0x26,},
+ {12000000, 440000000, 0x0, 0x92, 0xaa<<16|0xaa<<8|0xaa, 0x2, 0xb, 0x1a, 0x12, 0x7, 0x3b, 0x10, 0x3, 0x26,},
+ {12000000, 450000000, 0x0, 0x96, 0x0<<16|0x0<<8|0x0, 0x2, 0xb, 0x1b, 0x12, 0x8, 0x3c, 0x10, 0x3, 0x26,},
+ {12000000, 460000000, 0x0, 0x99, 0x55<<16|0x55<<8|0x55, 0x2, 0xb, 0x1b, 0x13, 0x8, 0x3d, 0x11, 0x3, 0x27,},
+ {12000000, 470000000, 0x0, 0x9c, 0xaa<<16|0xaa<<8|0xaa, 0x2, 0xc, 0x1b, 0x13, 0x8, 0x3e, 0x11, 0x3, 0x27,},
+ {12000000, 480000000, 0x0, 0xa0, 0x0<<16|0x0<<8|0x0, 0x2, 0xc, 0x1c, 0x13, 0x8, 0x40, 0x11, 0x3, 0x27,},
+ {12000000, 490000000, 0x0, 0xa3, 0x55<<16|0x55<<8|0x55, 0x2, 0xc, 0x1d, 0x14, 0x8, 0x42, 0x12, 0x3, 0x28,},
{12000000, 500000000, 0x0, 0xa6, 0xaa<<16|0xaa<<8|0xaa, 0x2, 0xc, 0x1d, 0x14, 0x9, 0x42, 0x12, 0x3, 0x28,},
{12000000, 510000000, 0x0, 0xaa, 0x0<<16|0x0<<8|0x0, 0x2, 0xc, 0x1e, 0x14, 0x9, 0x44, 0x12, 0x3, 0x28,},
{12000000, 520000000, 0x0, 0xad, 0x55<<16|0x55<<8|0x55, 0x2, 0xd, 0x1e, 0x15, 0x9, 0x45, 0x13, 0x3, 0x29,},
return ret;
}
-/*
-*static int sf_dphy_remove(struct platform_device *pdev)
-*{
-* struct sf_dphy *dphy = dev_get_drvdata(&pdev->dev);
-* reset_control_assert(dphy->sys_rst);
-* //reset_control_assert(dphy->txbytehs_rst);
-* clk_disable_unprepare(dphy->txesc_clk);
-* return 0;
-*}
-*/
-
-#if 0
-static u32 top_sys_read32(struct sf_dphy *priv, u32 reg)
-{
- return ioread32(priv->topsys + reg);
-}
-
-
-static inline void top_sys_write32(struct sf_dphy *priv, u32 reg, u32 val)
-{
- iowrite32(val, priv->topsys + reg);
-}
-
-static void dsi_csi2tx_sel(struct sf_dphy *priv, int sel)
-{
- u32 temp = 0;
- temp = top_sys_read32(priv, SCFG_DSI_CSI_SEL);
- temp &= ~(0x1);
- temp |= (sel & 0x1);
- top_sys_write32(priv, SCFG_DSI_CSI_SEL, temp);
-}
-
-static void dphy_clane_hs_txready_sel(struct sf_dphy *priv, u32 ready_sel)
-{
- top_sys_write32(priv, SCFG_TXREADY_SRC_SEL_D, ready_sel);
- top_sys_write32(priv, SCFG_TXREADY_SRC_SEL_C, ready_sel);
- top_sys_write32(priv, SCFG_HS_PRE_ZERO_T_D, 0x30);
- top_sys_write32(priv, SCFG_HS_PRE_ZERO_T_C, 0x30);
-}
-
-static void mipi_tx_lxn_set(struct sf_dphy *priv, u32 reg, u32 n_hstx, u32 p_hstx)
-{
- u32 temp = 0;
-
- temp = n_hstx;
- temp |= p_hstx << 5;
- top_sys_write32(priv, reg, temp);
-}
-
-static void dphy_config(struct sf_dphy *priv, int bit_rate)
-{
- int pre_div, fbk_int, extd_cycle_sel;
- int dhs_pre_time, dhs_zero_time, dhs_trial_time;
- int chs_pre_time, chs_zero_time, chs_trial_time;
- int chs_clk_pre_time, chs_clk_post_time;
- u32 set_val = 0;
-
- mipi_tx_lxn_set(priv, SCFG_L0N_L0P_HSTX, 0x10, 0x10);
- mipi_tx_lxn_set(priv, SCFG_L1N_L1P_HSTX, 0x10, 0x10);
- mipi_tx_lxn_set(priv, SCFG_L2N_L2P_HSTX, 0x10, 0x10);
- mipi_tx_lxn_set(priv, SCFG_L3N_L3P_HSTX, 0x10, 0x10);
- mipi_tx_lxn_set(priv, SCFG_L4N_L4P_HSTX, 0x10, 0x10);
-
- if(bit_rate == 80) {
- pre_div=0x1, fbk_int=2*0x33, extd_cycle_sel=0x4,
- dhs_pre_time=0xe, dhs_zero_time=0x1d, dhs_trial_time=0x15,
- chs_pre_time=0x5, chs_zero_time=0x2b, chs_trial_time=0xd,
- chs_clk_pre_time=0xf,
- chs_clk_post_time=0x71;
- } else if (bit_rate == 100) {
- pre_div=0x1, fbk_int=2*0x40, extd_cycle_sel=0x4,
- dhs_pre_time=0x10, dhs_zero_time=0x21, dhs_trial_time=0x17,
- chs_pre_time=0x7, chs_zero_time=0x35, chs_trial_time=0xf,
- chs_clk_pre_time=0xf,
- chs_clk_post_time=0x73;
- } else if (bit_rate == 200) {
- pre_div=0x1, fbk_int=2*0x40, extd_cycle_sel=0x3;
- dhs_pre_time=0xc, dhs_zero_time=0x1b, dhs_trial_time=0x13;
- chs_pre_time=0x7, chs_zero_time=0x35, chs_trial_time=0xf,
- chs_clk_pre_time=0x7,
- chs_clk_post_time=0x3f;
- } else if(bit_rate == 300) {
- pre_div=0x1, fbk_int=2*0x60, extd_cycle_sel=0x3,
- dhs_pre_time=0x11, dhs_zero_time=0x25, dhs_trial_time=0x19,
- chs_pre_time=0xa, chs_zero_time=0x50, chs_trial_time=0x15,
- chs_clk_pre_time=0x7,
- chs_clk_post_time=0x45;
- } else if(bit_rate == 400) {
- pre_div=0x1, fbk_int=2*0x40, extd_cycle_sel=0x2,
- dhs_pre_time=0xa, dhs_zero_time=0x18, dhs_trial_time=0x11,
- chs_pre_time=0x7, chs_zero_time=0x35, chs_trial_time=0xf,
- chs_clk_pre_time=0x3,
- chs_clk_post_time=0x25;
- } else if(bit_rate == 500 ) {
- pre_div=0x1, fbk_int=2*0x50, extd_cycle_sel=0x2,
- dhs_pre_time=0xc, dhs_zero_time=0x1d, dhs_trial_time=0x14,
- chs_pre_time=0x9, chs_zero_time=0x42, chs_trial_time=0x12,
- chs_clk_pre_time=0x3,
- chs_clk_post_time=0x28;
- } else if(bit_rate == 600 ) {
- pre_div=0x1, fbk_int=2*0x60, extd_cycle_sel=0x2,
- dhs_pre_time=0xe, dhs_zero_time=0x23, dhs_trial_time=0x17,
- chs_pre_time=0xa, chs_zero_time=0x50, chs_trial_time=0x15,
- chs_clk_pre_time=0x3,
- chs_clk_post_time=0x2b;
- } else if(bit_rate == 700) {
- pre_div=0x1, fbk_int=2*0x38, extd_cycle_sel=0x1,
- dhs_pre_time=0x8, dhs_zero_time=0x14, dhs_trial_time=0xf,
- chs_pre_time=0x6, chs_zero_time=0x2f, chs_trial_time=0xe,
- chs_clk_pre_time=0x1,
- chs_clk_post_time=0x16;
- } else if(bit_rate == 800 ) {
- pre_div=0x1, fbk_int=2*0x40, extd_cycle_sel=0x1,
- dhs_pre_time=0x9, dhs_zero_time=0x17, dhs_trial_time=0x10,
- chs_pre_time=0x7, chs_zero_time=0x35, chs_trial_time=0xf,
- chs_clk_pre_time=0x1,
- chs_clk_post_time=0x18;
- } else if(bit_rate == 900 ) {
- pre_div=0x1, fbk_int=2*0x48, extd_cycle_sel=0x1,
- dhs_pre_time=0xa, dhs_zero_time=0x19, dhs_trial_time=0x12,
- chs_pre_time=0x8, chs_zero_time=0x3c, chs_trial_time=0x10,
- chs_clk_pre_time=0x1,
- chs_clk_post_time=0x19;
- } else if(bit_rate == 1000) {
- pre_div=0x1, fbk_int=2*0x50, extd_cycle_sel=0x1,
- dhs_pre_time=0xb, dhs_zero_time=0x1c, dhs_trial_time=0x13,
- chs_pre_time=0x9, chs_zero_time=0x42, chs_trial_time=0x12,
- chs_clk_pre_time=0x1,
- chs_clk_post_time=0x1b;
- } else if(bit_rate == 1100) {
- pre_div=0x1, fbk_int=2*0x58, extd_cycle_sel=0x1,
- dhs_pre_time=0xc, dhs_zero_time=0x1e, dhs_trial_time=0x15,
- chs_pre_time=0x9, chs_zero_time=0x4a, chs_trial_time=0x14,
- chs_clk_pre_time=0x1,
- chs_clk_post_time=0x1d;
- } else if(bit_rate == 1200) {
- pre_div=0x1, fbk_int=2*0x60, extd_cycle_sel=0x1,
- dhs_pre_time=0xe, dhs_zero_time=0x20, dhs_trial_time=0x16,
- chs_pre_time=0xa, chs_zero_time=0x50, chs_trial_time=0x15,
- chs_clk_pre_time=0x1,
- chs_clk_post_time=0x1e;
- } else if(bit_rate == 1300) {
- pre_div=0x1, fbk_int=2*0x34, extd_cycle_sel=0x0,
- dhs_pre_time=0x7, dhs_zero_time=0x12, dhs_trial_time=0xd,
- chs_pre_time=0x5, chs_zero_time=0x2c, chs_trial_time=0xd,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0xf;
- } else if(bit_rate == 1400) {
- pre_div=0x1, fbk_int=2*0x38, extd_cycle_sel=0x0,
- dhs_pre_time=0x7, dhs_zero_time=0x14, dhs_trial_time=0xe,
- chs_pre_time=0x6, chs_zero_time=0x2f, chs_trial_time=0xe,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x10;
- } else if(bit_rate == 1500) {
- pre_div=0x1, fbk_int=2*0x3c, extd_cycle_sel=0x0,
- dhs_pre_time=0x8, dhs_zero_time=0x14, dhs_trial_time=0xf,
- chs_pre_time=0x6, chs_zero_time=0x32, chs_trial_time=0xe,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x11;
- } else if(bit_rate == 1600) {
- pre_div=0x1, fbk_int=2*0x40, extd_cycle_sel=0x0,
- dhs_pre_time=0x9, dhs_zero_time=0x15, dhs_trial_time=0x10,
- chs_pre_time=0x7, chs_zero_time=0x35, chs_trial_time=0xf,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x12;
- } else if(bit_rate == 1700) {
- pre_div=0x1, fbk_int=2*0x44, extd_cycle_sel=0x0,
- dhs_pre_time=0x9, dhs_zero_time=0x17, dhs_trial_time=0x10,
- chs_pre_time=0x7, chs_zero_time=0x39, chs_trial_time=0x10,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x12;
- } else if(bit_rate == 1800) {
- pre_div=0x1, fbk_int=2*0x48, extd_cycle_sel=0x0,
- dhs_pre_time=0xa, dhs_zero_time=0x18, dhs_trial_time=0x11,
- chs_pre_time=0x8, chs_zero_time=0x3c, chs_trial_time=0x10,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x13;
- } else if(bit_rate == 1900) {
- pre_div=0x1, fbk_int=2*0x4c, extd_cycle_sel=0x0,
- dhs_pre_time=0xa, dhs_zero_time=0x1a, dhs_trial_time=0x12,
- chs_pre_time=0x8, chs_zero_time=0x3f, chs_trial_time=0x11,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x14;
- } else if(bit_rate == 2000) {
- pre_div=0x1, fbk_int=2*0x50, extd_cycle_sel=0x0,
- dhs_pre_time=0xb, dhs_zero_time=0x1b, dhs_trial_time=0x13,
- chs_pre_time=0x9, chs_zero_time=0x42, chs_trial_time=0x12,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x15;
- } else if(bit_rate == 2100) {
- pre_div=0x1, fbk_int=2*0x54, extd_cycle_sel=0x0,
- dhs_pre_time=0xb, dhs_zero_time=0x1c, dhs_trial_time=0x13,
- chs_pre_time=0x9, chs_zero_time=0x46, chs_trial_time=0x13,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x15;
- } else if(bit_rate == 2200) {
- pre_div=0x1, fbk_int=2*0x5b, extd_cycle_sel=0x0,
- dhs_pre_time=0xc, dhs_zero_time=0x1d, dhs_trial_time=0x14,
- chs_pre_time=0x9, chs_zero_time=0x4a, chs_trial_time=0x14,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x16;
- } else if(bit_rate == 2300) {
- pre_div=0x1, fbk_int=2*0x5c, extd_cycle_sel=0x0,
- dhs_pre_time=0xc, dhs_zero_time=0x1f, dhs_trial_time=0x15,
- chs_pre_time=0xa, chs_zero_time=0x4c, chs_trial_time=0x14,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x17;
- } else if(bit_rate == 2400) {
- pre_div=0x1, fbk_int=2*0x60, extd_cycle_sel=0x0,
- dhs_pre_time=0xd, dhs_zero_time=0x20, dhs_trial_time=0x16,
- chs_pre_time=0xa, chs_zero_time=0x50, chs_trial_time=0x15,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x18;
- } else if(bit_rate == 2500) {
- pre_div=0x1, fbk_int=2*0x64, extd_cycle_sel=0x0,
- dhs_pre_time=0xe, dhs_zero_time=0x21, dhs_trial_time=0x16,
- chs_pre_time=0xb, chs_zero_time=0x53, chs_trial_time=0x16,
- chs_clk_pre_time=0x0,
- chs_clk_post_time=0x18;
- } else {
- //default bit_rate == 700
- pre_div=0x1, fbk_int=2*0x38, extd_cycle_sel=0x1,
- dhs_pre_time=0x8, dhs_zero_time=0x14, dhs_trial_time=0xf,
- chs_pre_time=0x6, chs_zero_time=0x2f, chs_trial_time=0xe,
- chs_clk_pre_time=0x1,
- chs_clk_post_time=0x16;
- }
- top_sys_write32(priv, SCFG_REFCLK_SEL, 0x3);
-
- set_val = 0
- | (1 << OFFSET_CFG_L1_SWAP_SEL)
- | (4 << OFFSET_CFG_L2_SWAP_SEL)
- | (2 << OFFSET_CFG_L3_SWAP_SEL)
- | (3 << OFFSET_CFG_L4_SWAP_SEL);
- top_sys_write32(priv, SCFG_LX_SWAP_SEL, set_val);
-
- set_val = 0
- | (0 << OFFSET_SCFG_PWRON_READY_N)
- | (1 << OFFSET_RG_CDTX_PLL_FM_EN)
- | (0 << OFFSET_SCFG_PLLSSC_EN)
- | (1 << OFFSET_RG_CDTX_PLL_LDO_STB_X2_EN);
- top_sys_write32(priv, SCFG_DBUS_PW_PLL_SSC_LD0, set_val);
-
- set_val = fbk_int
- | (pre_div << 9);
- top_sys_write32(priv, SCFG_RG_CDTX_PLL_FBK_PRE, set_val);
-
- top_sys_write32(priv, SCFG_RG_EXTD_CYCLE_SEL, extd_cycle_sel);
-
- set_val = chs_zero_time
- | (dhs_pre_time << OFFSET_DHS_PRE_TIME)
- | (dhs_trial_time << OFFSET_DHS_TRIAL_TIME)
- | (dhs_zero_time << OFFSET_DHS_ZERO_TIME);
- top_sys_write32(priv, SCFG_RG_CLANE_DLANE_TIME, set_val);
-
- set_val = chs_clk_post_time
- | (chs_clk_pre_time << OFFSET_CHS_PRE_TIME)
- | (chs_pre_time << OFFSET_CHS_TRIAL_TIME)
- | (chs_trial_time << OFFSET_CHS_ZERO_TIME);
- top_sys_write32(priv, SCFG_RG_CLANE_HS_TIME, set_val);
-
-}
-
-static void reset_dphy(struct sf_dphy *priv, int resetb)
-{
- u32 cfg_dsc_enable = 0x01;//bit0
-
- u32 precfg = top_sys_read32(priv, SCFG_PHY_RESETB);
- precfg &= ~(cfg_dsc_enable);
- precfg |= (resetb&cfg_dsc_enable);
- top_sys_write32(priv, SCFG_PHY_RESETB, precfg);
-}
-
-static void polling_dphy_lock(struct sf_dphy *priv)
-{
- int pll_unlock;
-
- udelay(10);
-
- do {
- pll_unlock = top_sys_read32(priv, SCFG_GRS_CDTX_PLL) >> 3;
- pll_unlock &= 0x1;
- } while(pll_unlock == 0x1);
-}
-
-static int sf_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
-{ //dev_info(dphy->dev,"--->sf_dphy_configure\n");
- struct sf_dphy *dphy = phy_get_drvdata(phy);
- uint32_t bit_rate = 800000000/1000000UL;//new mipi panel clock setting
- //uint32_t bit_rate = 500000000/1000000UL;//7110 mipi panel clock setting
-
-
- dphy_config(dphy, bit_rate);
- reset_dphy(dphy, 1);
- mdelay(10);
- polling_dphy_lock(dphy);
-
- //dev_info(dphy->dev,"--->sf_dphy_configure\n");
- return 0;
-}
-#endif
-
static int is_pll_locked(struct sf_dphy *dphy)
{
int tmp = sf_dphy_get_reg(dphy->topsys + 0x8,
const uint32_t AON_POWER_READY_N_active = 0;
dphy = phy_get_drvdata(phy);
//bitrate = 680000000;//1228M 60fps
- bitrate = 750000000;//1188M 60fps
+ //bitrate = 750000000;//1188M 60fps
+ // bitrate = 490000000;//1188M 60fps
+ bitrate = opts->mipi_dphy.hs_clk_rate;//1188M 60fps
+ printk("sys_m31_dphy_tx_configure opts->mipi_dphy.hs_clk_rate = %ld\n",opts->mipi_dphy.hs_clk_rate);
+
sf_dphy_set_reg(dphy->topsys + 0x8, 0x10,
RG_CDTX_L0N_HSTX_RES_SHIFT, RG_CDTX_L0N_HSTX_RES_MASK);
static int sf_dphy_init(struct phy *phy)
{
+ struct sf_dphy *dphy = phy_get_drvdata(phy);
+ uint32_t temp;
+ int ret;
+
+ temp = 0;
+ temp = sf_dphy_get_reg(dphy->aonsys, AON_GP_REG_SHIFT,AON_GP_REG_MASK);
+ dev_info(dphy->dev, "GET_AON_GP_REG\n");
+
+ if (!(temp & DPHY_TX_PSW_EN_MASK)) {
+ temp |= DPHY_TX_PSW_EN_MASK;
+ sf_dphy_set_reg(dphy->aonsys, temp,AON_GP_REG_SHIFT,AON_GP_REG_MASK);
+ }
+ dev_info(dphy->dev, "control ECO\n");
+
+ //pmic turn on
+ ret = regulator_enable(dphy->mipitx_0p9);
+ if (ret) {
+ dev_err(dphy->dev, "Cannot enable mipitx_0p9 regulator\n");
+ //goto err_reg_0p9;
+ }
+ udelay(100);
+ ret = regulator_enable(dphy->mipitx_1p8);
+ if (ret) {
+ dev_err(dphy->dev, "Cannot enable mipitx_1p8 regulator\n");
+ //goto err_reg_1p8;
+ }
+ udelay(100);
+ //mipi_pmic setting
+
return 0;
}
struct sf_dphy *dphy;
struct resource *res;
int ret;
- uint32_t temp;
dev_info(&pdev->dev, "sf_dphy_probe begin\n");
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
// this power switch control bit was added in ECO, check ECO item "aon psw_en" for detail
dev_info(dphy->dev, "control ECO\n");
dphy->aonsys = ioremap(0x17010000, 0x10000);
- temp = 0;
- temp = sf_dphy_get_reg(dphy->aonsys, AON_GP_REG_SHIFT,AON_GP_REG_MASK);
- dev_info(dphy->dev, "GET_AON_GP_REG\n");
-
- if (!(temp & DPHY_TX_PSW_EN_MASK)) {
- temp |= DPHY_TX_PSW_EN_MASK;
- sf_dphy_set_reg(dphy->aonsys, temp,AON_GP_REG_SHIFT,AON_GP_REG_MASK);
- }
- dev_info(dphy->dev, "control ECO\n");
//mipi_pmic setting
dphy->mipitx_1p8 = devm_regulator_get(&pdev->dev, "mipi_1p8");
if (IS_ERR(dphy->mipitx_0p9))
return PTR_ERR(dphy->mipitx_0p9);
- //pmic turn on
- ret = regulator_enable(dphy->mipitx_0p9);
- if (ret) {
- dev_err(&pdev->dev, "Cannot enable mipitx_0p9 regulator\n");
- //goto err_reg_0p9;
- }
- udelay(100);
- ret = regulator_enable(dphy->mipitx_1p8);
- if (ret) {
- dev_err(&pdev->dev, "Cannot enable mipitx_1p8 regulator\n");
- //goto err_reg_1p8;
- }
- udelay(100);
- //mipi_pmic setting
ret = sf_dphy_clkrst_get(&pdev->dev, dphy);