.. | .. |
---|
246 | 246 | struct phy *dcphy; |
---|
247 | 247 | union phy_configure_opts phy_opts; |
---|
248 | 248 | |
---|
| 249 | + bool disable_hold_mode; |
---|
| 250 | + bool auto_calc_mode; |
---|
249 | 251 | bool c_option; |
---|
250 | 252 | bool scrambling_en; |
---|
251 | 253 | unsigned int slice_width; |
---|
.. | .. |
---|
270 | 272 | u32 lanes; |
---|
271 | 273 | u32 format; |
---|
272 | 274 | unsigned long mode_flags; |
---|
273 | | - |
---|
| 275 | + u64 mipi_pixel_rate; |
---|
274 | 276 | const struct dw_mipi_dsi2_plat_data *pdata; |
---|
275 | 277 | struct rockchip_drm_sub_dev sub_dev; |
---|
276 | 278 | |
---|
277 | 279 | struct gpio_desc *te_gpio; |
---|
278 | | - bool user_split_mode; |
---|
279 | | - struct drm_property *user_split_mode_prop; |
---|
| 280 | + |
---|
| 281 | + /* split with other display interface */ |
---|
| 282 | + bool dual_connector_split; |
---|
| 283 | + bool left_display; |
---|
| 284 | + u32 split_area; |
---|
280 | 285 | }; |
---|
281 | 286 | |
---|
282 | 287 | static inline struct dw_mipi_dsi2 *host_to_dsi2(struct mipi_dsi_host *host) |
---|
.. | .. |
---|
450 | 455 | dw_mipi_dsi2_post_disable(dsi2->slave); |
---|
451 | 456 | } |
---|
452 | 457 | |
---|
453 | | -static void dw_mipi_dsi2_encoder_disable(struct drm_encoder *encoder) |
---|
| 458 | +static void dw_mipi_dsi2_encoder_atomic_disable(struct drm_encoder *encoder, |
---|
| 459 | + struct drm_atomic_state *state) |
---|
454 | 460 | { |
---|
455 | 461 | struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder); |
---|
456 | 462 | struct drm_crtc *crtc = encoder->crtc; |
---|
.. | .. |
---|
605 | 611 | |
---|
606 | 612 | static void dw_mipi_dsi2_phy_ratio_cfg(struct dw_mipi_dsi2 *dsi2) |
---|
607 | 613 | { |
---|
608 | | - struct drm_display_mode *mode = &dsi2->mode; |
---|
609 | 614 | u64 sys_clk = clk_get_rate(dsi2->sys_clk); |
---|
610 | | - u64 pixel_clk, ipi_clk, phy_hsclk; |
---|
| 615 | + u64 ipi_clk, phy_hsclk; |
---|
611 | 616 | u64 tmp; |
---|
612 | 617 | |
---|
613 | 618 | /* |
---|
.. | .. |
---|
621 | 626 | phy_hsclk = DIV_ROUND_CLOSEST_ULL(dsi2->lane_hs_rate * MSEC_PER_SEC, 16); |
---|
622 | 627 | |
---|
623 | 628 | /* IPI_RATIO_MAN_CFG = PHY_HSTX_CLK / IPI_CLK */ |
---|
624 | | - pixel_clk = mode->crtc_clock * MSEC_PER_SEC; |
---|
625 | | - ipi_clk = pixel_clk / 4; |
---|
| 629 | + ipi_clk = dsi2->mipi_pixel_rate; |
---|
| 630 | + if (!sys_clk || !ipi_clk) |
---|
| 631 | + return; |
---|
626 | 632 | |
---|
627 | 633 | tmp = DIV_ROUND_CLOSEST_ULL(phy_hsclk << 16, ipi_clk); |
---|
628 | 634 | regmap_write(dsi2->regmap, DSI2_PHY_IPI_RATIO_MAN_CFG, |
---|
.. | .. |
---|
662 | 668 | { |
---|
663 | 669 | dw_mipi_dsi2_phy_mode_cfg(dsi2); |
---|
664 | 670 | dw_mipi_dsi2_phy_clk_mode_cfg(dsi2); |
---|
| 671 | + |
---|
| 672 | + if (dsi2->auto_calc_mode) |
---|
| 673 | + return; |
---|
| 674 | + |
---|
665 | 675 | dw_mipi_dsi2_phy_ratio_cfg(dsi2); |
---|
666 | 676 | dw_mipi_dsi2_lp2hs_or_hs2lp_cfg(dsi2); |
---|
667 | 677 | |
---|
.. | .. |
---|
729 | 739 | regmap_write(dsi2->regmap, DSI2_IPI_PIX_PKT_CFG, MAX_PIX_PKT(val)); |
---|
730 | 740 | |
---|
731 | 741 | dw_mipi_dsi2_ipi_color_coding_cfg(dsi2); |
---|
| 742 | + |
---|
| 743 | + if (dsi2->auto_calc_mode) |
---|
| 744 | + return; |
---|
732 | 745 | |
---|
733 | 746 | /* |
---|
734 | 747 | * if the controller is intended to operate in data stream mode, |
---|
.. | .. |
---|
803 | 816 | |
---|
804 | 817 | /* there may be some timeout registers may be configured if desired */ |
---|
805 | 818 | |
---|
806 | | - dw_mipi_dsi2_work_mode(dsi2, MANUAL_MODE_EN); |
---|
| 819 | + dw_mipi_dsi2_work_mode(dsi2, dsi2->auto_calc_mode ? 0 : MANUAL_MODE_EN); |
---|
807 | 820 | dw_mipi_dsi2_phy_init(dsi2); |
---|
808 | 821 | dw_mipi_dsi2_tx_option_set(dsi2); |
---|
809 | 822 | dw_mipi_dsi2_irq_enable(dsi2, 1); |
---|
.. | .. |
---|
826 | 839 | |
---|
827 | 840 | static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2) |
---|
828 | 841 | { |
---|
| 842 | + u32 mode; |
---|
| 843 | + int ret; |
---|
| 844 | + |
---|
829 | 845 | dw_mipi_dsi2_ipi_set(dsi2); |
---|
| 846 | + |
---|
| 847 | + if (dsi2->auto_calc_mode) { |
---|
| 848 | + regmap_write(dsi2->regmap, DSI2_MODE_CTRL, AUTOCALC_MODE); |
---|
| 849 | + ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS, |
---|
| 850 | + mode, mode == IDLE_MODE, |
---|
| 851 | + 1000, MODE_STATUS_TIMEOUT_US); |
---|
| 852 | + if (ret < 0) |
---|
| 853 | + dev_err(dsi2->dev, "auto calculation training failed\n"); |
---|
| 854 | + } |
---|
830 | 855 | |
---|
831 | 856 | if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO) |
---|
832 | 857 | dw_mipi_dsi2_set_vid_mode(dsi2); |
---|
.. | .. |
---|
837 | 862 | dw_mipi_dsi2_enable(dsi2->slave); |
---|
838 | 863 | } |
---|
839 | 864 | |
---|
840 | | -static void dw_mipi_dsi2_encoder_enable(struct drm_encoder *encoder) |
---|
| 865 | +static void dw_mipi_dsi2_get_mipi_pixel_clk(struct dw_mipi_dsi2 *dsi2, |
---|
| 866 | + struct rockchip_crtc_state *s) |
---|
| 867 | +{ |
---|
| 868 | + struct drm_display_mode *mode = &dsi2->mode; |
---|
| 869 | + u8 k = dsi2->slave ? 2 : 1; |
---|
| 870 | + |
---|
| 871 | + /* 1.When MIPI works in uncompressed mode: |
---|
| 872 | + * (Video Timing Pixel Rate)/(4)=(MIPI Pixel ClockxK)=(dclk_out×K)=dclk_core |
---|
| 873 | + * 2.When MIPI works in compressed mode: |
---|
| 874 | + * MIPI Pixel Clock = cds_clk / 2 |
---|
| 875 | + * MIPI is configured as double channel display mode, K=2, otherwise K=1. |
---|
| 876 | + */ |
---|
| 877 | + if (dsi2->dsc_enable) { |
---|
| 878 | + dsi2->mipi_pixel_rate = s->dsc_cds_clk_rate / 2; |
---|
| 879 | + if (dsi2->slave) |
---|
| 880 | + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; |
---|
| 881 | + |
---|
| 882 | + return; |
---|
| 883 | + } |
---|
| 884 | + |
---|
| 885 | + dsi2->mipi_pixel_rate = (mode->crtc_clock * MSEC_PER_SEC) / (4 * k); |
---|
| 886 | + if (dsi2->slave) |
---|
| 887 | + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; |
---|
| 888 | +} |
---|
| 889 | + |
---|
| 890 | +static int dw_mipi_dsi2_encoder_mode_set(struct dw_mipi_dsi2 *dsi2, |
---|
| 891 | + struct drm_atomic_state *state) |
---|
| 892 | +{ |
---|
| 893 | + struct drm_encoder *encoder = &dsi2->encoder; |
---|
| 894 | + struct drm_connector *connector; |
---|
| 895 | + struct drm_connector_state *conn_state; |
---|
| 896 | + struct drm_crtc_state *crtc_state; |
---|
| 897 | + struct rockchip_crtc_state *vcstate; |
---|
| 898 | + const struct drm_display_mode *adjusted_mode; |
---|
| 899 | + struct drm_display_mode *mode = &dsi2->mode; |
---|
| 900 | + |
---|
| 901 | + connector = drm_atomic_get_new_connector_for_encoder(state, encoder); |
---|
| 902 | + if (!connector) |
---|
| 903 | + return -ENODEV; |
---|
| 904 | + |
---|
| 905 | + conn_state = drm_atomic_get_new_connector_state(state, connector); |
---|
| 906 | + if (!conn_state) |
---|
| 907 | + return -ENODEV; |
---|
| 908 | + |
---|
| 909 | + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); |
---|
| 910 | + if (!crtc_state) { |
---|
| 911 | + dev_err(dsi2->dev, "failed to get crtc state\n"); |
---|
| 912 | + return -ENODEV; |
---|
| 913 | + } |
---|
| 914 | + |
---|
| 915 | + vcstate = to_rockchip_crtc_state(crtc_state); |
---|
| 916 | + adjusted_mode = &crtc_state->adjusted_mode; |
---|
| 917 | + drm_mode_copy(mode, adjusted_mode); |
---|
| 918 | + |
---|
| 919 | + if (dsi2->dual_connector_split) |
---|
| 920 | + drm_mode_convert_to_origin_mode(mode); |
---|
| 921 | + |
---|
| 922 | + if (dsi2->slave) |
---|
| 923 | + drm_mode_copy(&dsi2->slave->mode, mode); |
---|
| 924 | + |
---|
| 925 | + dw_mipi_dsi2_get_mipi_pixel_clk(dsi2, vcstate); |
---|
| 926 | + |
---|
| 927 | + return 0; |
---|
| 928 | +} |
---|
| 929 | + |
---|
| 930 | +static void dw_mipi_dsi2_encoder_atomic_enable(struct drm_encoder *encoder, |
---|
| 931 | + struct drm_atomic_state *state) |
---|
841 | 932 | { |
---|
842 | 933 | struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder); |
---|
| 934 | + int ret; |
---|
| 935 | + |
---|
| 936 | + ret = dw_mipi_dsi2_encoder_mode_set(dsi2, state); |
---|
| 937 | + if (ret) { |
---|
| 938 | + dev_err(dsi2->dev, "failed to set dsi2 mode\n"); |
---|
| 939 | + return; |
---|
| 940 | + } |
---|
843 | 941 | |
---|
844 | 942 | dw_mipi_dsi2_get_lane_rate(dsi2); |
---|
845 | 943 | |
---|
.. | .. |
---|
867 | 965 | |
---|
868 | 966 | static int |
---|
869 | 967 | dw_mipi_dsi2_encoder_atomic_check(struct drm_encoder *encoder, |
---|
870 | | - struct drm_crtc_state *crtc_state, |
---|
871 | | - struct drm_connector_state *conn_state) |
---|
| 968 | + struct drm_crtc_state *crtc_state, |
---|
| 969 | + struct drm_connector_state *conn_state) |
---|
872 | 970 | { |
---|
873 | 971 | |
---|
874 | 972 | struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); |
---|
.. | .. |
---|
906 | 1004 | if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO)) { |
---|
907 | 1005 | s->output_flags |= ROCKCHIP_OUTPUT_MIPI_DS_MODE; |
---|
908 | 1006 | s->soft_te = dsi2->te_gpio ? true : false; |
---|
909 | | - s->hold_mode = true; |
---|
| 1007 | + s->hold_mode = dsi2->disable_hold_mode ? false : true; |
---|
910 | 1008 | } |
---|
911 | 1009 | |
---|
912 | 1010 | if (dsi2->slave) { |
---|
.. | .. |
---|
915 | 1013 | s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; |
---|
916 | 1014 | |
---|
917 | 1015 | s->output_if |= VOP_OUTPUT_IF_MIPI1; |
---|
| 1016 | + } |
---|
| 1017 | + |
---|
| 1018 | + if (dsi2->dual_connector_split) { |
---|
| 1019 | + s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CONNECTOR_SPLIT_MODE; |
---|
| 1020 | + |
---|
| 1021 | + if (dsi2->left_display) |
---|
| 1022 | + s->output_if_left_panel |= dsi2->id ? |
---|
| 1023 | + VOP_OUTPUT_IF_MIPI1 : |
---|
| 1024 | + VOP_OUTPUT_IF_MIPI0; |
---|
918 | 1025 | } |
---|
919 | 1026 | |
---|
920 | 1027 | if (dsi2->dsc_enable) { |
---|
.. | .. |
---|
931 | 1038 | } |
---|
932 | 1039 | |
---|
933 | 1040 | return 0; |
---|
934 | | -} |
---|
935 | | - |
---|
936 | | -static void |
---|
937 | | -dw_mipi_dsi2_encoder_atomic_mode_set(struct drm_encoder *encoder, |
---|
938 | | - struct drm_crtc_state *crtc_state, |
---|
939 | | - struct drm_connector_state *connector_state) |
---|
940 | | -{ |
---|
941 | | - struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder); |
---|
942 | | - |
---|
943 | | - drm_mode_copy(&dsi2->mode, &crtc_state->adjusted_mode); |
---|
944 | | - if (dsi2->slave) |
---|
945 | | - drm_mode_copy(&dsi2->slave->mode, &crtc_state->adjusted_mode); |
---|
946 | 1041 | } |
---|
947 | 1042 | |
---|
948 | 1043 | static void dw_mipi_dsi2_loader_protect(struct dw_mipi_dsi2 *dsi2, bool on) |
---|
.. | .. |
---|
980 | 1075 | |
---|
981 | 1076 | static const struct drm_encoder_helper_funcs |
---|
982 | 1077 | dw_mipi_dsi2_encoder_helper_funcs = { |
---|
983 | | - .enable = dw_mipi_dsi2_encoder_enable, |
---|
984 | | - .disable = dw_mipi_dsi2_encoder_disable, |
---|
| 1078 | + .atomic_enable = dw_mipi_dsi2_encoder_atomic_enable, |
---|
| 1079 | + .atomic_disable = dw_mipi_dsi2_encoder_atomic_disable, |
---|
985 | 1080 | .atomic_check = dw_mipi_dsi2_encoder_atomic_check, |
---|
986 | | - .atomic_mode_set = dw_mipi_dsi2_encoder_atomic_mode_set, |
---|
987 | 1081 | }; |
---|
988 | 1082 | |
---|
989 | 1083 | static int dw_mipi_dsi2_connector_get_modes(struct drm_connector *connector) |
---|
.. | .. |
---|
1065 | 1159 | drm_connector_cleanup(connector); |
---|
1066 | 1160 | } |
---|
1067 | 1161 | |
---|
| 1162 | +static int |
---|
| 1163 | +dw_mipi_dsi2_atomic_connector_get_property(struct drm_connector *connector, |
---|
| 1164 | + const struct drm_connector_state *state, |
---|
| 1165 | + struct drm_property *property, |
---|
| 1166 | + uint64_t *val) |
---|
| 1167 | +{ |
---|
| 1168 | + struct rockchip_drm_private *private = connector->dev->dev_private; |
---|
| 1169 | + struct dw_mipi_dsi2 *dsi2 = con_to_dsi2(connector); |
---|
| 1170 | + |
---|
| 1171 | + if (property == private->split_area_prop) { |
---|
| 1172 | + switch (dsi2->split_area) { |
---|
| 1173 | + case 1: |
---|
| 1174 | + *val = ROCKCHIP_DRM_SPLIT_LEFT_SIDE; |
---|
| 1175 | + break; |
---|
| 1176 | + case 2: |
---|
| 1177 | + *val = ROCKCHIP_DRM_SPLIT_RIGHT_SIDE; |
---|
| 1178 | + break; |
---|
| 1179 | + default: |
---|
| 1180 | + *val = ROCKCHIP_DRM_SPLIT_UNSET; |
---|
| 1181 | + break; |
---|
| 1182 | + } |
---|
| 1183 | + } |
---|
| 1184 | + |
---|
| 1185 | + return 0; |
---|
| 1186 | +} |
---|
| 1187 | + |
---|
1068 | 1188 | static const struct drm_connector_funcs dw_mipi_dsi2_atomic_connector_funcs = { |
---|
1069 | 1189 | .fill_modes = drm_helper_probe_single_connector_modes, |
---|
1070 | 1190 | .detect = dw_mipi_dsi2_connector_detect, |
---|
.. | .. |
---|
1072 | 1192 | .reset = drm_atomic_helper_connector_reset, |
---|
1073 | 1193 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
---|
1074 | 1194 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
---|
| 1195 | + .atomic_get_property = dw_mipi_dsi2_atomic_connector_get_property, |
---|
1075 | 1196 | }; |
---|
1076 | 1197 | |
---|
1077 | 1198 | static int dw_mipi_dsi2_dual_channel_probe(struct dw_mipi_dsi2 *dsi2) |
---|
.. | .. |
---|
1093 | 1214 | dsi2->slave->master = dsi2; |
---|
1094 | 1215 | dsi2->lanes /= 2; |
---|
1095 | 1216 | |
---|
| 1217 | + dsi2->slave->auto_calc_mode = dsi2->auto_calc_mode; |
---|
1096 | 1218 | dsi2->slave->lanes = dsi2->lanes; |
---|
1097 | 1219 | dsi2->slave->channel = dsi2->channel; |
---|
1098 | 1220 | dsi2->slave->format = dsi2->format; |
---|
.. | .. |
---|
1143 | 1265 | dsi2->slave->dsc_enable = dsi2->dsc_enable; |
---|
1144 | 1266 | } |
---|
1145 | 1267 | |
---|
| 1268 | + if (!dsi2->dsc_enable) |
---|
| 1269 | + return 0; |
---|
| 1270 | + |
---|
1146 | 1271 | of_property_read_u32(np, "slice-width", &dsi2->slice_width); |
---|
1147 | 1272 | of_property_read_u32(np, "slice-height", &dsi2->slice_height); |
---|
1148 | 1273 | of_property_read_u8(np, "version-major", &dsi2->version_major); |
---|
.. | .. |
---|
1178 | 1303 | len -= header->payload_length; |
---|
1179 | 1304 | } |
---|
1180 | 1305 | |
---|
| 1306 | + if (!pps) { |
---|
| 1307 | + dev_err(dsi2->dev, "not found dsc pps definition\n"); |
---|
| 1308 | + return -EINVAL; |
---|
| 1309 | + } |
---|
| 1310 | + |
---|
1181 | 1311 | dsi2->pps = pps; |
---|
| 1312 | + |
---|
| 1313 | + if (dsi2->slave) { |
---|
| 1314 | + u16 pic_width = be16_to_cpu(pps->pic_width) / 2; |
---|
| 1315 | + |
---|
| 1316 | + dsi2->pps->pic_width = cpu_to_be16(pic_width); |
---|
| 1317 | + dev_info(dsi2->dev, "dsc pic_width change from %d to %d\n", |
---|
| 1318 | + pic_width * 2, pic_width); |
---|
| 1319 | + } |
---|
1182 | 1320 | |
---|
1183 | 1321 | return 0; |
---|
1184 | 1322 | } |
---|
.. | .. |
---|
1218 | 1356 | static int dw_mipi_dsi2_register_sub_dev(struct dw_mipi_dsi2 *dsi2, |
---|
1219 | 1357 | struct drm_connector *connector) |
---|
1220 | 1358 | { |
---|
| 1359 | + struct rockchip_drm_private *private; |
---|
1221 | 1360 | struct device *dev = dsi2->dev; |
---|
1222 | | - struct drm_property *prop; |
---|
1223 | | - int ret; |
---|
1224 | 1361 | |
---|
1225 | | - prop = drm_property_create_bool(dsi2->drm_dev, DRM_MODE_PROP_IMMUTABLE, |
---|
1226 | | - "USER_SPLIT_MODE"); |
---|
1227 | | - if (!prop) { |
---|
1228 | | - ret = -EINVAL; |
---|
1229 | | - DRM_DEV_ERROR(dev, "create user split mode prop failed\n"); |
---|
1230 | | - goto connector_cleanup; |
---|
1231 | | - } |
---|
| 1362 | + private = connector->dev->dev_private; |
---|
1232 | 1363 | |
---|
1233 | | - dsi2->user_split_mode_prop = prop; |
---|
1234 | | - drm_object_attach_property(&connector->base, |
---|
1235 | | - dsi2->user_split_mode_prop, |
---|
1236 | | - dsi2->user_split_mode ? 1 : 0); |
---|
| 1364 | + if (dsi2->split_area) |
---|
| 1365 | + drm_object_attach_property(&connector->base, |
---|
| 1366 | + private->split_area_prop, |
---|
| 1367 | + dsi2->split_area); |
---|
1237 | 1368 | |
---|
1238 | 1369 | dsi2->sub_dev.connector = connector; |
---|
1239 | 1370 | dsi2->sub_dev.of_node = dev->of_node; |
---|
.. | .. |
---|
1241 | 1372 | rockchip_drm_register_sub_dev(&dsi2->sub_dev); |
---|
1242 | 1373 | |
---|
1243 | 1374 | return 0; |
---|
1244 | | - |
---|
1245 | | -connector_cleanup: |
---|
1246 | | - connector->funcs->destroy(connector); |
---|
1247 | | - |
---|
1248 | | - return ret; |
---|
1249 | 1375 | } |
---|
1250 | 1376 | |
---|
1251 | 1377 | static int dw_mipi_dsi2_bind(struct device *dev, struct device *master, |
---|
.. | .. |
---|
1563 | 1689 | dsi2->id = id; |
---|
1564 | 1690 | dsi2->pdata = of_device_get_match_data(dev); |
---|
1565 | 1691 | platform_set_drvdata(pdev, dsi2); |
---|
1566 | | - dsi2->user_split_mode = device_property_read_bool(dev, "user-split-mode"); |
---|
| 1692 | + |
---|
| 1693 | + if (device_property_read_bool(dev, "auto-calculation-mode")) |
---|
| 1694 | + dsi2->auto_calc_mode = true; |
---|
| 1695 | + |
---|
| 1696 | + if (device_property_read_bool(dev, "disable-hold-mode")) |
---|
| 1697 | + dsi2->disable_hold_mode = true; |
---|
| 1698 | + |
---|
| 1699 | + if (device_property_read_bool(dev, "dual-connector-split")) { |
---|
| 1700 | + dsi2->dual_connector_split = true; |
---|
| 1701 | + |
---|
| 1702 | + if (device_property_read_bool(dev, "left-display")) |
---|
| 1703 | + dsi2->left_display = true; |
---|
| 1704 | + } |
---|
| 1705 | + |
---|
| 1706 | + if (device_property_read_u32(dev, "split-area", &dsi2->split_area)) |
---|
| 1707 | + dsi2->split_area = 0; |
---|
1567 | 1708 | |
---|
1568 | 1709 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1569 | 1710 | regs = devm_ioremap_resource(dev, res); |
---|