1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020 Rockchip Electronics Co. Ltd. 4 * 5 * Author: Guochun Huang <hero.huang@rock-chips.com> 6 */ 7 8 #include <drm/drm_mipi_dsi.h> 9 10 #include <config.h> 11 #include <common.h> 12 #include <errno.h> 13 #include <malloc.h> 14 #include <video.h> 15 #include <backlight.h> 16 #include <spi.h> 17 #include <asm/gpio.h> 18 #include <dm/device.h> 19 #include <dm/read.h> 20 #include <dm/uclass.h> 21 #include <dm/uclass-id.h> 22 #include <linux/media-bus-format.h> 23 #include <power/regulator.h> 24 25 #include "rk628.h" 26 #include "panel.h" 27 28 void *kmemdup(const void *src, size_t len, gfp_t gfp) 29 { 30 void *p; 31 32 p = kmalloc(len, gfp); 33 if (p) 34 memcpy(p, src, len); 35 return p; 36 } 37 38 static int 39 dsi_panel_parse_cmds(const u8 *data, int blen, struct panel_cmds *pcmds) 40 { 41 unsigned int len; 42 u8 *buf, *bp; 43 struct cmd_ctrl_hdr *dchdr; 44 int i, cnt; 45 46 if (!pcmds) 47 return -EINVAL; 48 49 buf = kmemdup(data, blen, GFP_KERNEL); 50 if (!buf) 51 return -ENOMEM; 52 53 /* scan init commands */ 54 bp = buf; 55 len = blen; 56 cnt = 0; 57 while (len > sizeof(*dchdr)) { 58 dchdr = (struct cmd_ctrl_hdr *)bp; 59 60 if (dchdr->dlen > len) { 61 pr_err("%s: error, len=%d", __func__, dchdr->dlen); 62 return -EINVAL; 63 } 64 65 bp += sizeof(*dchdr); 66 len -= sizeof(*dchdr); 67 bp += dchdr->dlen; 68 len -= dchdr->dlen; 69 cnt++; 70 } 71 72 if (len != 0) { 73 pr_err("%s: dcs_cmd=%x len=%d error!", __func__, buf[0], blen); 74 kfree(buf); 75 return -EINVAL; 76 } 77 78 pcmds->cmds = kcalloc(cnt, sizeof(struct cmd_desc), GFP_KERNEL); 79 if (!pcmds->cmds) { 80 kfree(buf); 81 return -ENOMEM; 82 } 83 84 pcmds->cmd_cnt = cnt; 85 pcmds->buf = buf; 86 pcmds->blen = blen; 87 88 bp = buf; 89 len = blen; 90 for (i = 0; i < cnt; i++) { 91 dchdr = (struct cmd_ctrl_hdr *)bp; 92 len -= sizeof(*dchdr); 93 bp += sizeof(*dchdr); 94 pcmds->cmds[i].dchdr = *dchdr; 95 pcmds->cmds[i].payload = bp; 96 bp += dchdr->dlen; 97 len -= dchdr->dlen; 98 } 99 100 return 0; 101 } 102 103 static int dsi_panel_get_cmds(struct rk628 *rk628, ofnode dsi_np) 104 { 105 ofnode np; 106 const void *data; 107 int len; 108 int ret, err; 109 110 np = ofnode_find_subnode(dsi_np, "rk628-panel"); 111 if (!ofnode_valid(np)) 112 return -EINVAL; 113 114 data = ofnode_get_property(np, "panel-init-sequence", &len); 115 if (data) { 116 rk628->panel->on_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL); 117 if (!rk628->panel->on_cmds) 118 return -ENOMEM; 119 120 err = dsi_panel_parse_cmds(data, len, rk628->panel->on_cmds); 121 if (err) { 122 printf("rk628 failed to parse dsi panel init sequence\n"); 123 ret = err; 124 goto init_err; 125 } 126 } 127 128 data = ofnode_get_property(np, "panel-exit-sequence", &len); 129 if (data) { 130 rk628->panel->off_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL); 131 if (!rk628->panel->off_cmds) { 132 ret = -ENOMEM; 133 goto on_err; 134 } 135 136 err = dsi_panel_parse_cmds(data, len, rk628->panel->off_cmds); 137 if (err) { 138 printf("rk628 failed to parse dsi panel exit sequence\n"); 139 ret = err; 140 goto exit_err; 141 } 142 } 143 144 return 0; 145 146 exit_err: 147 kfree(rk628->panel->off_cmds); 148 on_err: 149 kfree(rk628->panel->on_cmds->cmds); 150 kfree(rk628->panel->on_cmds->buf); 151 init_err: 152 kfree(rk628->panel->on_cmds); 153 154 return ret; 155 } 156 157 int rk628_panel_info_get(struct rk628 *rk628, ofnode np) 158 { 159 struct rk628_panel_simple *panel; 160 struct udevice *dev = rk628->dev; 161 int ret; 162 163 panel = devm_kzalloc(dev, sizeof(struct rk628_panel_simple), GFP_KERNEL); 164 if (!panel) 165 return -ENOMEM; 166 167 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "panel-power-supply", &panel->supply); 168 if (ret && ret != -ENOENT) { 169 printf("rk628 failed to get power supply: %d\n", ret); 170 return ret; 171 } 172 173 ret = gpio_request_by_name(dev, "panel-enable-gpios", 0, 174 &panel->enable_gpio, GPIOD_IS_OUT); 175 if (ret && ret != -ENOENT) { 176 printf("%s: Cannot get enable GPIO: %d\n", __func__, ret); 177 return ret; 178 } 179 180 ret = gpio_request_by_name(dev, "panel-reset-gpios", 0, 181 &panel->reset_gpio, GPIOD_IS_OUT); 182 if (ret && ret != -ENOENT) { 183 printf("%s: Cannot get reset GPIO: %d\n", __func__, ret); 184 return ret; 185 } 186 187 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 188 "panel-backlight", &panel->backlight); 189 if (ret && ret != -ENOENT) { 190 printf("%s: Cannot get backlight: %d\n", __func__, ret); 191 return ret; 192 } 193 194 panel->delay.prepare = dev_read_u32_default(dev, "panel-prepare-delay-ms", 0); 195 panel->delay.enable = dev_read_u32_default(dev, "panel-enable-delay-ms", 0); 196 panel->delay.disable = dev_read_u32_default(dev, "panel-disable-delay-ms", 0); 197 panel->delay.unprepare = dev_read_u32_default(dev, "panel-unprepare-delay-ms", 0); 198 panel->delay.reset = dev_read_u32_default(dev, "panel-reset-delay-ms", 0); 199 panel->delay.init = dev_read_u32_default(dev, "panel-init-delay-ms", 0); 200 201 rk628->panel = panel; 202 203 if (rk628_output_is_dsi(rk628)) { 204 ret = dsi_panel_get_cmds(rk628, np); 205 if (ret) { 206 dev_err(dev, "failed to get cmds\n"); 207 return ret; 208 } 209 } 210 211 return 0; 212 } 213 214 void rk628_panel_prepare(struct rk628 *rk628) 215 { 216 struct rk628_panel_simple *p = rk628->panel; 217 218 if (!p) 219 return; 220 221 if (p->supply) 222 regulator_set_enable(p->supply, 1); 223 224 if (dm_gpio_is_valid(&p->enable_gpio)) 225 dm_gpio_set_value(&p->enable_gpio, 1); 226 227 if (p->delay.prepare) 228 mdelay(p->delay.prepare); 229 230 if (dm_gpio_is_valid(&p->reset_gpio)) 231 dm_gpio_set_value(&p->reset_gpio, 1); 232 233 if (p->delay.reset) 234 mdelay(p->delay.reset); 235 236 if (dm_gpio_is_valid(&p->reset_gpio)) 237 dm_gpio_set_value(&p->reset_gpio, 0); 238 239 if (p->delay.init) 240 mdelay(p->delay.init); 241 } 242 243 void rk628_panel_enable(struct rk628 *rk628) 244 { 245 struct rk628_panel_simple *p = rk628->panel; 246 247 if (!p) 248 return; 249 250 if (p->delay.enable) 251 mdelay(p->delay.enable); 252 253 254 if (p->backlight) 255 backlight_enable(p->backlight); 256 } 257 258 void rk628_panel_unprepare(struct rk628 *rk628) 259 { 260 struct rk628_panel_simple *p = rk628->panel; 261 262 if (!p) 263 return; 264 265 if (dm_gpio_is_valid(&p->reset_gpio)) 266 dm_gpio_set_value(&p->reset_gpio, 1); 267 268 if (dm_gpio_is_valid(&p->enable_gpio)) 269 dm_gpio_set_value(&p->enable_gpio, 0); 270 271 if (rk628->panel->supply) 272 regulator_set_enable(p->supply, 0); 273 274 if (p->delay.unprepare) 275 mdelay(p->delay.unprepare); 276 } 277 278 void rk628_panel_disable(struct rk628 *rk628) 279 { 280 struct rk628_panel_simple *p = rk628->panel; 281 282 if (!p) 283 return; 284 285 if (p->backlight) 286 backlight_disable(p->backlight); 287 288 if (p->delay.disable) 289 mdelay(p->delay.disable); 290 } 291