diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_mixer.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 126 |
1 files changed, 66 insertions, 60 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index a41c84ee3a2d..820b76234ef4 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -40,8 +40,6 @@ | |||
40 | #include "exynos_drm_iommu.h" | 40 | #include "exynos_drm_iommu.h" |
41 | #include "exynos_mixer.h" | 41 | #include "exynos_mixer.h" |
42 | 42 | ||
43 | #define get_mixer_manager(dev) platform_get_drvdata(to_platform_device(dev)) | ||
44 | |||
45 | #define MIXER_WIN_NR 3 | 43 | #define MIXER_WIN_NR 3 |
46 | #define MIXER_DEFAULT_WIN 0 | 44 | #define MIXER_DEFAULT_WIN 0 |
47 | 45 | ||
@@ -86,6 +84,7 @@ enum mixer_version_id { | |||
86 | }; | 84 | }; |
87 | 85 | ||
88 | struct mixer_context { | 86 | struct mixer_context { |
87 | struct exynos_drm_manager manager; | ||
89 | struct platform_device *pdev; | 88 | struct platform_device *pdev; |
90 | struct device *dev; | 89 | struct device *dev; |
91 | struct drm_device *drm_dev; | 90 | struct drm_device *drm_dev; |
@@ -104,6 +103,11 @@ struct mixer_context { | |||
104 | atomic_t wait_vsync_event; | 103 | atomic_t wait_vsync_event; |
105 | }; | 104 | }; |
106 | 105 | ||
106 | static inline struct mixer_context *mgr_to_mixer(struct exynos_drm_manager *mgr) | ||
107 | { | ||
108 | return container_of(mgr, struct mixer_context, manager); | ||
109 | } | ||
110 | |||
107 | struct mixer_drv_data { | 111 | struct mixer_drv_data { |
108 | enum mixer_version_id version; | 112 | enum mixer_version_id version; |
109 | bool is_vp_enabled; | 113 | bool is_vp_enabled; |
@@ -854,7 +858,7 @@ static int mixer_initialize(struct exynos_drm_manager *mgr, | |||
854 | struct drm_device *drm_dev) | 858 | struct drm_device *drm_dev) |
855 | { | 859 | { |
856 | int ret; | 860 | int ret; |
857 | struct mixer_context *mixer_ctx = mgr->ctx; | 861 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
858 | struct exynos_drm_private *priv; | 862 | struct exynos_drm_private *priv; |
859 | priv = drm_dev->dev_private; | 863 | priv = drm_dev->dev_private; |
860 | 864 | ||
@@ -885,7 +889,7 @@ static int mixer_initialize(struct exynos_drm_manager *mgr, | |||
885 | 889 | ||
886 | static void mixer_mgr_remove(struct exynos_drm_manager *mgr) | 890 | static void mixer_mgr_remove(struct exynos_drm_manager *mgr) |
887 | { | 891 | { |
888 | struct mixer_context *mixer_ctx = mgr->ctx; | 892 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
889 | 893 | ||
890 | if (is_drm_iommu_supported(mixer_ctx->drm_dev)) | 894 | if (is_drm_iommu_supported(mixer_ctx->drm_dev)) |
891 | drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); | 895 | drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); |
@@ -893,7 +897,7 @@ static void mixer_mgr_remove(struct exynos_drm_manager *mgr) | |||
893 | 897 | ||
894 | static int mixer_enable_vblank(struct exynos_drm_manager *mgr) | 898 | static int mixer_enable_vblank(struct exynos_drm_manager *mgr) |
895 | { | 899 | { |
896 | struct mixer_context *mixer_ctx = mgr->ctx; | 900 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
897 | struct mixer_resources *res = &mixer_ctx->mixer_res; | 901 | struct mixer_resources *res = &mixer_ctx->mixer_res; |
898 | 902 | ||
899 | if (!mixer_ctx->powered) { | 903 | if (!mixer_ctx->powered) { |
@@ -910,7 +914,7 @@ static int mixer_enable_vblank(struct exynos_drm_manager *mgr) | |||
910 | 914 | ||
911 | static void mixer_disable_vblank(struct exynos_drm_manager *mgr) | 915 | static void mixer_disable_vblank(struct exynos_drm_manager *mgr) |
912 | { | 916 | { |
913 | struct mixer_context *mixer_ctx = mgr->ctx; | 917 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
914 | struct mixer_resources *res = &mixer_ctx->mixer_res; | 918 | struct mixer_resources *res = &mixer_ctx->mixer_res; |
915 | 919 | ||
916 | /* disable vsync interrupt */ | 920 | /* disable vsync interrupt */ |
@@ -920,7 +924,7 @@ static void mixer_disable_vblank(struct exynos_drm_manager *mgr) | |||
920 | static void mixer_win_mode_set(struct exynos_drm_manager *mgr, | 924 | static void mixer_win_mode_set(struct exynos_drm_manager *mgr, |
921 | struct exynos_drm_overlay *overlay) | 925 | struct exynos_drm_overlay *overlay) |
922 | { | 926 | { |
923 | struct mixer_context *mixer_ctx = mgr->ctx; | 927 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
924 | struct hdmi_win_data *win_data; | 928 | struct hdmi_win_data *win_data; |
925 | int win; | 929 | int win; |
926 | 930 | ||
@@ -971,7 +975,7 @@ static void mixer_win_mode_set(struct exynos_drm_manager *mgr, | |||
971 | 975 | ||
972 | static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) | 976 | static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) |
973 | { | 977 | { |
974 | struct mixer_context *mixer_ctx = mgr->ctx; | 978 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
975 | int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; | 979 | int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; |
976 | 980 | ||
977 | DRM_DEBUG_KMS("win: %d\n", win); | 981 | DRM_DEBUG_KMS("win: %d\n", win); |
@@ -993,7 +997,7 @@ static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) | |||
993 | 997 | ||
994 | static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) | 998 | static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) |
995 | { | 999 | { |
996 | struct mixer_context *mixer_ctx = mgr->ctx; | 1000 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
997 | struct mixer_resources *res = &mixer_ctx->mixer_res; | 1001 | struct mixer_resources *res = &mixer_ctx->mixer_res; |
998 | int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; | 1002 | int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; |
999 | unsigned long flags; | 1003 | unsigned long flags; |
@@ -1021,7 +1025,7 @@ static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) | |||
1021 | 1025 | ||
1022 | static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) | 1026 | static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) |
1023 | { | 1027 | { |
1024 | struct mixer_context *mixer_ctx = mgr->ctx; | 1028 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
1025 | 1029 | ||
1026 | mutex_lock(&mixer_ctx->mixer_mutex); | 1030 | mutex_lock(&mixer_ctx->mixer_mutex); |
1027 | if (!mixer_ctx->powered) { | 1031 | if (!mixer_ctx->powered) { |
@@ -1048,7 +1052,7 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) | |||
1048 | 1052 | ||
1049 | static void mixer_window_suspend(struct exynos_drm_manager *mgr) | 1053 | static void mixer_window_suspend(struct exynos_drm_manager *mgr) |
1050 | { | 1054 | { |
1051 | struct mixer_context *ctx = mgr->ctx; | 1055 | struct mixer_context *ctx = mgr_to_mixer(mgr); |
1052 | struct hdmi_win_data *win_data; | 1056 | struct hdmi_win_data *win_data; |
1053 | int i; | 1057 | int i; |
1054 | 1058 | ||
@@ -1062,7 +1066,7 @@ static void mixer_window_suspend(struct exynos_drm_manager *mgr) | |||
1062 | 1066 | ||
1063 | static void mixer_window_resume(struct exynos_drm_manager *mgr) | 1067 | static void mixer_window_resume(struct exynos_drm_manager *mgr) |
1064 | { | 1068 | { |
1065 | struct mixer_context *ctx = mgr->ctx; | 1069 | struct mixer_context *ctx = mgr_to_mixer(mgr); |
1066 | struct hdmi_win_data *win_data; | 1070 | struct hdmi_win_data *win_data; |
1067 | int i; | 1071 | int i; |
1068 | 1072 | ||
@@ -1077,7 +1081,7 @@ static void mixer_window_resume(struct exynos_drm_manager *mgr) | |||
1077 | 1081 | ||
1078 | static void mixer_poweron(struct exynos_drm_manager *mgr) | 1082 | static void mixer_poweron(struct exynos_drm_manager *mgr) |
1079 | { | 1083 | { |
1080 | struct mixer_context *ctx = mgr->ctx; | 1084 | struct mixer_context *ctx = mgr_to_mixer(mgr); |
1081 | struct mixer_resources *res = &ctx->mixer_res; | 1085 | struct mixer_resources *res = &ctx->mixer_res; |
1082 | 1086 | ||
1083 | mutex_lock(&ctx->mixer_mutex); | 1087 | mutex_lock(&ctx->mixer_mutex); |
@@ -1111,7 +1115,7 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) | |||
1111 | 1115 | ||
1112 | static void mixer_poweroff(struct exynos_drm_manager *mgr) | 1116 | static void mixer_poweroff(struct exynos_drm_manager *mgr) |
1113 | { | 1117 | { |
1114 | struct mixer_context *ctx = mgr->ctx; | 1118 | struct mixer_context *ctx = mgr_to_mixer(mgr); |
1115 | struct mixer_resources *res = &ctx->mixer_res; | 1119 | struct mixer_resources *res = &ctx->mixer_res; |
1116 | 1120 | ||
1117 | mutex_lock(&ctx->mixer_mutex); | 1121 | mutex_lock(&ctx->mixer_mutex); |
@@ -1187,11 +1191,6 @@ static struct exynos_drm_manager_ops mixer_manager_ops = { | |||
1187 | .win_disable = mixer_win_disable, | 1191 | .win_disable = mixer_win_disable, |
1188 | }; | 1192 | }; |
1189 | 1193 | ||
1190 | static struct exynos_drm_manager mixer_manager = { | ||
1191 | .type = EXYNOS_DISPLAY_TYPE_HDMI, | ||
1192 | .ops = &mixer_manager_ops, | ||
1193 | }; | ||
1194 | |||
1195 | static struct mixer_drv_data exynos5420_mxr_drv_data = { | 1194 | static struct mixer_drv_data exynos5420_mxr_drv_data = { |
1196 | .version = MXR_VER_128_0_0_184, | 1195 | .version = MXR_VER_128_0_0_184, |
1197 | .is_vp_enabled = 0, | 1196 | .is_vp_enabled = 0, |
@@ -1249,48 +1248,17 @@ MODULE_DEVICE_TABLE(of, mixer_match_types); | |||
1249 | 1248 | ||
1250 | static int mixer_bind(struct device *dev, struct device *manager, void *data) | 1249 | static int mixer_bind(struct device *dev, struct device *manager, void *data) |
1251 | { | 1250 | { |
1252 | struct platform_device *pdev = to_platform_device(dev); | 1251 | struct mixer_context *ctx = dev_get_drvdata(dev); |
1253 | struct drm_device *drm_dev = data; | 1252 | struct drm_device *drm_dev = data; |
1254 | struct mixer_context *ctx; | ||
1255 | struct mixer_drv_data *drv; | ||
1256 | int ret; | 1253 | int ret; |
1257 | 1254 | ||
1258 | dev_info(dev, "probe start\n"); | 1255 | ret = mixer_initialize(&ctx->manager, drm_dev); |
1259 | |||
1260 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); | ||
1261 | if (!ctx) { | ||
1262 | DRM_ERROR("failed to alloc mixer context.\n"); | ||
1263 | return -ENOMEM; | ||
1264 | } | ||
1265 | |||
1266 | mutex_init(&ctx->mixer_mutex); | ||
1267 | |||
1268 | if (dev->of_node) { | ||
1269 | const struct of_device_id *match; | ||
1270 | match = of_match_node(mixer_match_types, dev->of_node); | ||
1271 | drv = (struct mixer_drv_data *)match->data; | ||
1272 | } else { | ||
1273 | drv = (struct mixer_drv_data *) | ||
1274 | platform_get_device_id(pdev)->driver_data; | ||
1275 | } | ||
1276 | |||
1277 | ctx->pdev = pdev; | ||
1278 | ctx->dev = dev; | ||
1279 | ctx->vp_enabled = drv->is_vp_enabled; | ||
1280 | ctx->has_sclk = drv->has_sclk; | ||
1281 | ctx->mxr_ver = drv->version; | ||
1282 | init_waitqueue_head(&ctx->wait_vsync_queue); | ||
1283 | atomic_set(&ctx->wait_vsync_event, 0); | ||
1284 | |||
1285 | mixer_manager.ctx = ctx; | ||
1286 | ret = mixer_initialize(&mixer_manager, drm_dev); | ||
1287 | if (ret) | 1256 | if (ret) |
1288 | return ret; | 1257 | return ret; |
1289 | 1258 | ||
1290 | platform_set_drvdata(pdev, &mixer_manager); | 1259 | ret = exynos_drm_crtc_create(&ctx->manager); |
1291 | ret = exynos_drm_crtc_create(&mixer_manager); | ||
1292 | if (ret) { | 1260 | if (ret) { |
1293 | mixer_mgr_remove(&mixer_manager); | 1261 | mixer_mgr_remove(&ctx->manager); |
1294 | return ret; | 1262 | return ret; |
1295 | } | 1263 | } |
1296 | 1264 | ||
@@ -1301,11 +1269,9 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) | |||
1301 | 1269 | ||
1302 | static void mixer_unbind(struct device *dev, struct device *master, void *data) | 1270 | static void mixer_unbind(struct device *dev, struct device *master, void *data) |
1303 | { | 1271 | { |
1304 | struct exynos_drm_manager *mgr = dev_get_drvdata(dev); | 1272 | struct mixer_context *ctx = dev_get_drvdata(dev); |
1305 | 1273 | ||
1306 | dev_info(dev, "remove successful\n"); | 1274 | mixer_mgr_remove(&ctx->manager); |
1307 | |||
1308 | mixer_mgr_remove(mgr); | ||
1309 | 1275 | ||
1310 | pm_runtime_disable(dev); | 1276 | pm_runtime_disable(dev); |
1311 | } | 1277 | } |
@@ -1317,22 +1283,62 @@ static const struct component_ops mixer_component_ops = { | |||
1317 | 1283 | ||
1318 | static int mixer_probe(struct platform_device *pdev) | 1284 | static int mixer_probe(struct platform_device *pdev) |
1319 | { | 1285 | { |
1286 | struct device *dev = &pdev->dev; | ||
1287 | struct mixer_drv_data *drv; | ||
1288 | struct mixer_context *ctx; | ||
1320 | int ret; | 1289 | int ret; |
1321 | 1290 | ||
1291 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); | ||
1292 | if (!ctx) { | ||
1293 | DRM_ERROR("failed to alloc mixer context.\n"); | ||
1294 | return -ENOMEM; | ||
1295 | } | ||
1296 | |||
1297 | mutex_init(&ctx->mixer_mutex); | ||
1298 | |||
1299 | ctx->manager.type = EXYNOS_DISPLAY_TYPE_HDMI; | ||
1300 | ctx->manager.ops = &mixer_manager_ops; | ||
1301 | |||
1302 | if (dev->of_node) { | ||
1303 | const struct of_device_id *match; | ||
1304 | |||
1305 | match = of_match_node(mixer_match_types, dev->of_node); | ||
1306 | drv = (struct mixer_drv_data *)match->data; | ||
1307 | } else { | ||
1308 | drv = (struct mixer_drv_data *) | ||
1309 | platform_get_device_id(pdev)->driver_data; | ||
1310 | } | ||
1311 | |||
1312 | ctx->pdev = pdev; | ||
1313 | ctx->dev = dev; | ||
1314 | ctx->vp_enabled = drv->is_vp_enabled; | ||
1315 | ctx->has_sclk = drv->has_sclk; | ||
1316 | ctx->mxr_ver = drv->version; | ||
1317 | init_waitqueue_head(&ctx->wait_vsync_queue); | ||
1318 | atomic_set(&ctx->wait_vsync_event, 0); | ||
1319 | |||
1320 | platform_set_drvdata(pdev, ctx); | ||
1321 | |||
1322 | ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, | 1322 | ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, |
1323 | mixer_manager.type); | 1323 | ctx->manager.type); |
1324 | if (ret) | 1324 | if (ret) |
1325 | return ret; | 1325 | return ret; |
1326 | 1326 | ||
1327 | ret = component_add(&pdev->dev, &mixer_component_ops); | 1327 | ret = component_add(&pdev->dev, &mixer_component_ops); |
1328 | if (ret) | 1328 | if (ret) { |
1329 | exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); | 1329 | exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); |
1330 | return ret; | ||
1331 | } | ||
1332 | |||
1333 | pm_runtime_enable(dev); | ||
1330 | 1334 | ||
1331 | return ret; | 1335 | return ret; |
1332 | } | 1336 | } |
1333 | 1337 | ||
1334 | static int mixer_remove(struct platform_device *pdev) | 1338 | static int mixer_remove(struct platform_device *pdev) |
1335 | { | 1339 | { |
1340 | pm_runtime_disable(&pdev->dev); | ||
1341 | |||
1336 | component_del(&pdev->dev, &mixer_component_ops); | 1342 | component_del(&pdev->dev, &mixer_component_ops); |
1337 | exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); | 1343 | exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); |
1338 | 1344 | ||