.. | .. |
---|
12 | 12 | #include <common.h> |
---|
13 | 13 | #include <errno.h> |
---|
14 | 14 | #include <asm/unaligned.h> |
---|
| 15 | +#include <asm/gpio.h> |
---|
15 | 16 | #include <asm/io.h> |
---|
16 | 17 | #include <asm/hardware.h> |
---|
17 | 18 | #include <dm/device.h> |
---|
.. | .. |
---|
22 | 23 | #include <asm/arch-rockchip/clock.h> |
---|
23 | 24 | #include <linux/iopoll.h> |
---|
24 | 25 | |
---|
25 | | -#include "rockchip_bridge.h" |
---|
26 | 26 | #include "rockchip_display.h" |
---|
27 | 27 | #include "rockchip_crtc.h" |
---|
28 | 28 | #include "rockchip_connector.h" |
---|
.. | .. |
---|
289 | 289 | struct drm_display_mode mode; |
---|
290 | 290 | bool data_swap; |
---|
291 | 291 | |
---|
| 292 | + struct gpio_desc te_gpio; |
---|
292 | 293 | struct mipi_dsi_device *device; |
---|
293 | 294 | struct mipi_dphy_configure mipi_dphy_cfg; |
---|
294 | 295 | const struct dw_mipi_dsi2_plat_data *pdata; |
---|
.. | .. |
---|
693 | 694 | static int dw_mipi_dsi2_connector_pre_init(struct rockchip_connector *conn, |
---|
694 | 695 | struct display_state *state) |
---|
695 | 696 | { |
---|
| 697 | + struct connector_state *conn_state = &state->conn_state; |
---|
696 | 698 | struct dw_mipi_dsi2 *dsi2 = dev_get_priv(conn->dev); |
---|
697 | 699 | struct mipi_dsi_host *host = dev_get_platdata(dsi2->dev); |
---|
698 | 700 | struct mipi_dsi_device *device; |
---|
699 | 701 | char name[20]; |
---|
700 | | - struct udevice *dev; |
---|
701 | 702 | |
---|
702 | | - device = calloc(1, sizeof(struct dw_mipi_dsi2)); |
---|
703 | | - if (!device) |
---|
704 | | - return -ENOMEM; |
---|
| 703 | + conn_state->type = DRM_MODE_CONNECTOR_DSI; |
---|
705 | 704 | |
---|
706 | | - if (conn->bridge) |
---|
707 | | - dev = conn->bridge->dev; |
---|
708 | | - else if (conn->panel) |
---|
709 | | - dev = conn->panel->dev; |
---|
710 | | - else |
---|
711 | | - return -ENODEV; |
---|
| 705 | + if (conn->bridge) { |
---|
| 706 | + device = dev_get_platdata(conn->bridge->dev); |
---|
| 707 | + if (!device) |
---|
| 708 | + return -ENODEV; |
---|
712 | 709 | |
---|
713 | | - device->dev = dev; |
---|
714 | | - device->host = host; |
---|
715 | | - device->lanes = dev_read_u32_default(dev, "dsi,lanes", 4); |
---|
716 | | - device->channel = dev_read_u32_default(dev, "reg", 0); |
---|
717 | | - device->format = dev_read_u32_default(dev, "dsi,format", |
---|
718 | | - MIPI_DSI_FMT_RGB888); |
---|
719 | | - device->mode_flags = dev_read_u32_default(dev, "dsi,flags", |
---|
720 | | - MIPI_DSI_MODE_VIDEO | |
---|
721 | | - MIPI_DSI_MODE_VIDEO_BURST | |
---|
722 | | - MIPI_DSI_MODE_VIDEO_HBP | |
---|
723 | | - MIPI_DSI_MODE_LPM | |
---|
724 | | - MIPI_DSI_MODE_EOT_PACKET); |
---|
| 710 | + device->host = host; |
---|
| 711 | + sprintf(name, "%s.%d", host->dev->name, device->channel); |
---|
| 712 | + device_set_name(conn->bridge->dev, name); |
---|
| 713 | + mipi_dsi_attach(device); |
---|
| 714 | + } |
---|
725 | 715 | |
---|
726 | | - sprintf(name, "%s.%d", host->dev->name, device->channel); |
---|
727 | | - device_set_name(dev, name); |
---|
728 | | - dsi2->device = device; |
---|
729 | | - dev->parent_platdata = device; |
---|
| 716 | + return 0; |
---|
| 717 | +} |
---|
730 | 718 | |
---|
731 | | - mipi_dsi_attach(dsi2->device); |
---|
| 719 | +static int dw_mipi_dsi2_get_dsc_params_from_sink(struct dw_mipi_dsi2 *dsi2) |
---|
| 720 | +{ |
---|
| 721 | + struct udevice *dev = dsi2->device->dev; |
---|
| 722 | + struct rockchip_cmd_header *header; |
---|
| 723 | + struct drm_dsc_picture_parameter_set *pps = NULL; |
---|
| 724 | + u8 *dsc_packed_pps; |
---|
| 725 | + const void *data; |
---|
| 726 | + int len; |
---|
| 727 | + |
---|
| 728 | + dsi2->c_option = dev_read_bool(dev, "phy-c-option"); |
---|
| 729 | + dsi2->scrambling_en = dev_read_bool(dev, "scrambling-enable"); |
---|
| 730 | + dsi2->dsc_enable = dev_read_bool(dev, "compressed-data"); |
---|
| 731 | + |
---|
| 732 | + if (dsi2->slave) { |
---|
| 733 | + dsi2->slave->c_option = dsi2->c_option; |
---|
| 734 | + dsi2->slave->scrambling_en = dsi2->scrambling_en; |
---|
| 735 | + dsi2->slave->dsc_enable = dsi2->dsc_enable; |
---|
| 736 | + } |
---|
| 737 | + |
---|
| 738 | + dsi2->slice_width = dev_read_u32_default(dev, "slice-width", 0); |
---|
| 739 | + dsi2->slice_height = dev_read_u32_default(dev, "slice-height", 0); |
---|
| 740 | + dsi2->version_major = dev_read_u32_default(dev, "version-major", 0); |
---|
| 741 | + dsi2->version_minor = dev_read_u32_default(dev, "version-minor", 0); |
---|
| 742 | + |
---|
| 743 | + data = dev_read_prop(dev, "panel-init-sequence", &len); |
---|
| 744 | + if (!data) |
---|
| 745 | + return -EINVAL; |
---|
| 746 | + |
---|
| 747 | + while (len > sizeof(*header)) { |
---|
| 748 | + header = (struct rockchip_cmd_header *)data; |
---|
| 749 | + data += sizeof(*header); |
---|
| 750 | + len -= sizeof(*header); |
---|
| 751 | + |
---|
| 752 | + if (header->payload_length > len) |
---|
| 753 | + return -EINVAL; |
---|
| 754 | + |
---|
| 755 | + if (header->data_type == MIPI_DSI_PICTURE_PARAMETER_SET) { |
---|
| 756 | + dsc_packed_pps = calloc(1, header->payload_length); |
---|
| 757 | + if (!dsc_packed_pps) |
---|
| 758 | + return -ENOMEM; |
---|
| 759 | + |
---|
| 760 | + memcpy(dsc_packed_pps, data, header->payload_length); |
---|
| 761 | + pps = (struct drm_dsc_picture_parameter_set *)dsc_packed_pps; |
---|
| 762 | + break; |
---|
| 763 | + } |
---|
| 764 | + |
---|
| 765 | + data += header->payload_length; |
---|
| 766 | + len -= header->payload_length; |
---|
| 767 | + } |
---|
| 768 | + |
---|
| 769 | + dsi2->pps = pps; |
---|
732 | 770 | |
---|
733 | 771 | return 0; |
---|
734 | 772 | } |
---|
.. | .. |
---|
792 | 830 | dsi2->slave->dcphy.phy = phy; |
---|
793 | 831 | if (phy->funcs && phy->funcs->init) |
---|
794 | 832 | return phy->funcs->init(phy); |
---|
| 833 | + } |
---|
| 834 | + |
---|
| 835 | + dw_mipi_dsi2_get_dsc_params_from_sink(dsi2); |
---|
| 836 | + |
---|
| 837 | + if (dm_gpio_is_valid(&dsi2->te_gpio)) { |
---|
| 838 | + cstate->soft_te = true; |
---|
| 839 | + conn_state->te_gpio = &dsi2->te_gpio; |
---|
795 | 840 | } |
---|
796 | 841 | |
---|
797 | 842 | if (dsi2->dsc_enable) { |
---|
.. | .. |
---|
905 | 950 | |
---|
906 | 951 | static void dw_mipi_dsi2_phy_clk_mode_cfg(struct dw_mipi_dsi2 *dsi2) |
---|
907 | 952 | { |
---|
908 | | - u32 sys_clk = SYS_CLK / MSEC_PER_SEC; |
---|
| 953 | + u32 sys_clk = SYS_CLK / USEC_PER_SEC; |
---|
909 | 954 | u32 esc_clk_div; |
---|
910 | 955 | u32 val = 0; |
---|
911 | 956 | |
---|
.. | .. |
---|
913 | 958 | val |= NON_CONTINUOUS_CLK; |
---|
914 | 959 | |
---|
915 | 960 | /* The Escape clock ranges from 1MHz to 20MHz. */ |
---|
916 | | - esc_clk_div = DIV_ROUND_UP(sys_clk, 10 * 2); |
---|
| 961 | + esc_clk_div = DIV_ROUND_UP(sys_clk, 20 * 2); |
---|
917 | 962 | val |= PHY_LPTX_CLK_DIV(esc_clk_div); |
---|
918 | 963 | |
---|
919 | 964 | dsi_write(dsi2, DSI2_PHY_CLK_CFG, val); |
---|
.. | .. |
---|
1102 | 1147 | return 0; |
---|
1103 | 1148 | } |
---|
1104 | 1149 | |
---|
| 1150 | +static int dw_mipi_dsi2_connector_mode_valid(struct rockchip_connector *conn, |
---|
| 1151 | + struct display_state *state) |
---|
| 1152 | +{ |
---|
| 1153 | + struct dw_mipi_dsi2 *dsi2 = dev_get_priv(conn->dev); |
---|
| 1154 | + struct connector_state *conn_state = &state->conn_state; |
---|
| 1155 | + u8 min_pixels = dsi2->slave ? 8 : 4; |
---|
| 1156 | + struct videomode vm; |
---|
| 1157 | + |
---|
| 1158 | + drm_display_mode_to_videomode(&conn_state->mode, &vm); |
---|
| 1159 | + |
---|
| 1160 | + /* |
---|
| 1161 | + * the minimum region size (HSA,HBP,HACT,HFP) is 4 pixels |
---|
| 1162 | + * which is the ip known issues and limitations. |
---|
| 1163 | + */ |
---|
| 1164 | + if (!(vm.hsync_len < min_pixels || vm.hback_porch < min_pixels || |
---|
| 1165 | + vm.hfront_porch < min_pixels || vm.hactive < min_pixels)) |
---|
| 1166 | + return MODE_OK; |
---|
| 1167 | + |
---|
| 1168 | + if (vm.hsync_len < min_pixels) |
---|
| 1169 | + vm.hsync_len = min_pixels; |
---|
| 1170 | + |
---|
| 1171 | + if (vm.hback_porch < min_pixels) |
---|
| 1172 | + vm.hback_porch = min_pixels; |
---|
| 1173 | + |
---|
| 1174 | + if (vm.hfront_porch < min_pixels) |
---|
| 1175 | + vm.hfront_porch = min_pixels; |
---|
| 1176 | + |
---|
| 1177 | + if (vm.hactive < min_pixels) |
---|
| 1178 | + vm.hactive = min_pixels; |
---|
| 1179 | + |
---|
| 1180 | + drm_display_mode_from_videomode(&vm, &conn_state->mode); |
---|
| 1181 | + |
---|
| 1182 | + return MODE_OK; |
---|
| 1183 | +} |
---|
| 1184 | + |
---|
1105 | 1185 | static const struct rockchip_connector_funcs dw_mipi_dsi2_connector_funcs = { |
---|
1106 | 1186 | .pre_init = dw_mipi_dsi2_connector_pre_init, |
---|
1107 | 1187 | .init = dw_mipi_dsi2_connector_init, |
---|
.. | .. |
---|
1109 | 1189 | .unprepare = dw_mipi_dsi2_connector_unprepare, |
---|
1110 | 1190 | .enable = dw_mipi_dsi2_connector_enable, |
---|
1111 | 1191 | .disable = dw_mipi_dsi2_connector_disable, |
---|
| 1192 | + .mode_valid = dw_mipi_dsi2_connector_mode_valid, |
---|
1112 | 1193 | }; |
---|
1113 | 1194 | |
---|
1114 | 1195 | static int dw_mipi_dsi2_probe(struct udevice *dev) |
---|
.. | .. |
---|
1132 | 1213 | id = of_alias_get_id(ofnode_to_np(dev->node), "dsi"); |
---|
1133 | 1214 | if (id < 0) |
---|
1134 | 1215 | id = 0; |
---|
| 1216 | + |
---|
| 1217 | + ret = gpio_request_by_name(dev, "te-gpios", 0, |
---|
| 1218 | + &dsi2->te_gpio, GPIOD_IS_IN); |
---|
| 1219 | + if (ret && ret != -ENOENT) { |
---|
| 1220 | + printf("%s: Cannot get TE GPIO: %d\n", __func__, ret); |
---|
| 1221 | + return ret; |
---|
| 1222 | + } |
---|
1135 | 1223 | |
---|
1136 | 1224 | dsi2->dev = dev; |
---|
1137 | 1225 | dsi2->pdata = pdata; |
---|
.. | .. |
---|
1185 | 1273 | return dw_mipi_dsi2_transfer(dsi2, msg); |
---|
1186 | 1274 | } |
---|
1187 | 1275 | |
---|
1188 | | -static int dw_mipi_dsi2_get_dsc_params_from_sink(struct dw_mipi_dsi2 *dsi2) |
---|
1189 | | -{ |
---|
1190 | | - struct udevice *dev = dsi2->device->dev; |
---|
1191 | | - struct rockchip_cmd_header *header; |
---|
1192 | | - struct drm_dsc_picture_parameter_set *pps = NULL; |
---|
1193 | | - u8 *dsc_packed_pps; |
---|
1194 | | - const void *data; |
---|
1195 | | - int len; |
---|
1196 | | - |
---|
1197 | | - dsi2->c_option = dev_read_bool(dev, "phy-c-option"); |
---|
1198 | | - dsi2->scrambling_en = dev_read_bool(dev, "scrambling-enable"); |
---|
1199 | | - dsi2->dsc_enable = dev_read_bool(dev, "compressed-data"); |
---|
1200 | | - |
---|
1201 | | - if (dsi2->slave) { |
---|
1202 | | - dsi2->slave->c_option = dsi2->c_option; |
---|
1203 | | - dsi2->slave->scrambling_en = dsi2->scrambling_en; |
---|
1204 | | - dsi2->slave->dsc_enable = dsi2->dsc_enable; |
---|
1205 | | - } |
---|
1206 | | - |
---|
1207 | | - dsi2->slice_width = dev_read_u32_default(dev, "slice-width", 0); |
---|
1208 | | - dsi2->slice_height = dev_read_u32_default(dev, "slice-height", 0); |
---|
1209 | | - dsi2->version_major = dev_read_u32_default(dev, "version-major", 0); |
---|
1210 | | - dsi2->version_minor = dev_read_u32_default(dev, "version-minor", 0); |
---|
1211 | | - |
---|
1212 | | - data = dev_read_prop(dev, "panel-init-sequence", &len); |
---|
1213 | | - if (!data) |
---|
1214 | | - return -EINVAL; |
---|
1215 | | - |
---|
1216 | | - while (len > sizeof(*header)) { |
---|
1217 | | - header = (struct rockchip_cmd_header *)data; |
---|
1218 | | - data += sizeof(*header); |
---|
1219 | | - len -= sizeof(*header); |
---|
1220 | | - |
---|
1221 | | - if (header->payload_length > len) |
---|
1222 | | - return -EINVAL; |
---|
1223 | | - |
---|
1224 | | - if (header->data_type == MIPI_DSI_PICTURE_PARAMETER_SET) { |
---|
1225 | | - dsc_packed_pps = calloc(1, header->payload_length); |
---|
1226 | | - if (!dsc_packed_pps) |
---|
1227 | | - return -ENOMEM; |
---|
1228 | | - |
---|
1229 | | - memcpy(dsc_packed_pps, data, header->payload_length); |
---|
1230 | | - pps = (struct drm_dsc_picture_parameter_set *)dsc_packed_pps; |
---|
1231 | | - break; |
---|
1232 | | - } |
---|
1233 | | - |
---|
1234 | | - data += header->payload_length; |
---|
1235 | | - len -= header->payload_length; |
---|
1236 | | - } |
---|
1237 | | - |
---|
1238 | | - dsi2->pps = pps; |
---|
1239 | | - |
---|
1240 | | - return 0; |
---|
1241 | | -} |
---|
1242 | | - |
---|
1243 | 1276 | static int dw_mipi_dsi2_host_attach(struct mipi_dsi_host *host, |
---|
1244 | 1277 | struct mipi_dsi_device *device) |
---|
1245 | 1278 | { |
---|
.. | .. |
---|
1252 | 1285 | dsi2->channel = device->channel; |
---|
1253 | 1286 | dsi2->format = device->format; |
---|
1254 | 1287 | dsi2->mode_flags = device->mode_flags; |
---|
1255 | | - |
---|
1256 | | - dw_mipi_dsi2_get_dsc_params_from_sink(dsi2); |
---|
| 1288 | + dsi2->device = device; |
---|
1257 | 1289 | |
---|
1258 | 1290 | return 0; |
---|
1259 | 1291 | } |
---|
.. | .. |
---|
1273 | 1305 | return dm_scan_fdt_dev(dev); |
---|
1274 | 1306 | } |
---|
1275 | 1307 | |
---|
| 1308 | +static int dw_mipi_dsi2_child_post_bind(struct udevice *dev) |
---|
| 1309 | +{ |
---|
| 1310 | + struct mipi_dsi_host *host = dev_get_platdata(dev->parent); |
---|
| 1311 | + struct mipi_dsi_device *device = dev_get_parent_platdata(dev); |
---|
| 1312 | + char name[20]; |
---|
| 1313 | + |
---|
| 1314 | + sprintf(name, "%s.%d", host->dev->name, device->channel); |
---|
| 1315 | + device_set_name(dev, name); |
---|
| 1316 | + |
---|
| 1317 | + device->dev = dev; |
---|
| 1318 | + device->host = host; |
---|
| 1319 | + device->lanes = dev_read_u32_default(dev, "dsi,lanes", 4); |
---|
| 1320 | + device->format = dev_read_u32_default(dev, "dsi,format", |
---|
| 1321 | + MIPI_DSI_FMT_RGB888); |
---|
| 1322 | + device->mode_flags = dev_read_u32_default(dev, "dsi,flags", |
---|
| 1323 | + MIPI_DSI_MODE_VIDEO | |
---|
| 1324 | + MIPI_DSI_MODE_VIDEO_BURST | |
---|
| 1325 | + MIPI_DSI_MODE_VIDEO_HBP | |
---|
| 1326 | + MIPI_DSI_MODE_LPM | |
---|
| 1327 | + MIPI_DSI_MODE_EOT_PACKET); |
---|
| 1328 | + device->channel = dev_read_u32_default(dev, "reg", 0); |
---|
| 1329 | + |
---|
| 1330 | + return 0; |
---|
| 1331 | +} |
---|
| 1332 | + |
---|
| 1333 | +static int dw_mipi_dsi2_child_pre_probe(struct udevice *dev) |
---|
| 1334 | +{ |
---|
| 1335 | + struct mipi_dsi_device *device = dev_get_parent_platdata(dev); |
---|
| 1336 | + int ret; |
---|
| 1337 | + |
---|
| 1338 | + ret = mipi_dsi_attach(device); |
---|
| 1339 | + if (ret) { |
---|
| 1340 | + dev_err(dev, "mipi_dsi_attach() failed: %d\n", ret); |
---|
| 1341 | + return ret; |
---|
| 1342 | + } |
---|
| 1343 | + |
---|
| 1344 | + return 0; |
---|
| 1345 | +} |
---|
| 1346 | + |
---|
1276 | 1347 | U_BOOT_DRIVER(dw_mipi_dsi2) = { |
---|
1277 | 1348 | .name = "dw_mipi_dsi2", |
---|
1278 | 1349 | .id = UCLASS_DISPLAY, |
---|
.. | .. |
---|
1280 | 1351 | .probe = dw_mipi_dsi2_probe, |
---|
1281 | 1352 | .bind = dw_mipi_dsi2_bind, |
---|
1282 | 1353 | .priv_auto_alloc_size = sizeof(struct dw_mipi_dsi2), |
---|
| 1354 | + .per_child_platdata_auto_alloc_size = sizeof(struct mipi_dsi_device), |
---|
1283 | 1355 | .platdata_auto_alloc_size = sizeof(struct mipi_dsi_host), |
---|
| 1356 | + .child_post_bind = dw_mipi_dsi2_child_post_bind, |
---|
| 1357 | + .child_pre_probe = dw_mipi_dsi2_child_pre_probe, |
---|
1284 | 1358 | }; |
---|