diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_mixer.c')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 7529946d0a74..e8b4ec84b312 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
| @@ -76,7 +76,7 @@ struct mixer_resources { | |||
| 76 | struct clk *vp; | 76 | struct clk *vp; |
| 77 | struct clk *sclk_mixer; | 77 | struct clk *sclk_mixer; |
| 78 | struct clk *sclk_hdmi; | 78 | struct clk *sclk_hdmi; |
| 79 | struct clk *sclk_dac; | 79 | struct clk *mout_mixer; |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | enum mixer_version_id { | 82 | enum mixer_version_id { |
| @@ -93,6 +93,7 @@ struct mixer_context { | |||
| 93 | bool interlace; | 93 | bool interlace; |
| 94 | bool powered; | 94 | bool powered; |
| 95 | bool vp_enabled; | 95 | bool vp_enabled; |
| 96 | bool has_sclk; | ||
| 96 | u32 int_en; | 97 | u32 int_en; |
| 97 | 98 | ||
| 98 | struct mutex mixer_mutex; | 99 | struct mutex mixer_mutex; |
| @@ -106,6 +107,7 @@ struct mixer_context { | |||
| 106 | struct mixer_drv_data { | 107 | struct mixer_drv_data { |
| 107 | enum mixer_version_id version; | 108 | enum mixer_version_id version; |
| 108 | bool is_vp_enabled; | 109 | bool is_vp_enabled; |
| 110 | bool has_sclk; | ||
| 109 | }; | 111 | }; |
| 110 | 112 | ||
| 111 | static const u8 filter_y_horiz_tap8[] = { | 113 | static const u8 filter_y_horiz_tap8[] = { |
| @@ -363,6 +365,11 @@ static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable) | |||
| 363 | vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); | 365 | vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); |
| 364 | mixer_reg_writemask(res, MXR_CFG, val, | 366 | mixer_reg_writemask(res, MXR_CFG, val, |
| 365 | MXR_CFG_VP_ENABLE); | 367 | MXR_CFG_VP_ENABLE); |
| 368 | |||
| 369 | /* control blending of graphic layer 0 */ | ||
| 370 | mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val, | ||
| 371 | MXR_GRP_CFG_BLEND_PRE_MUL | | ||
| 372 | MXR_GRP_CFG_PIXEL_BLEND_EN); | ||
| 366 | } | 373 | } |
| 367 | break; | 374 | break; |
| 368 | } | 375 | } |
| @@ -809,19 +816,23 @@ static int vp_resources_init(struct mixer_context *mixer_ctx) | |||
| 809 | dev_err(dev, "failed to get clock 'vp'\n"); | 816 | dev_err(dev, "failed to get clock 'vp'\n"); |
| 810 | return -ENODEV; | 817 | return -ENODEV; |
| 811 | } | 818 | } |
| 812 | mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); | ||
| 813 | if (IS_ERR(mixer_res->sclk_mixer)) { | ||
| 814 | dev_err(dev, "failed to get clock 'sclk_mixer'\n"); | ||
| 815 | return -ENODEV; | ||
| 816 | } | ||
| 817 | mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac"); | ||
| 818 | if (IS_ERR(mixer_res->sclk_dac)) { | ||
| 819 | dev_err(dev, "failed to get clock 'sclk_dac'\n"); | ||
| 820 | return -ENODEV; | ||
| 821 | } | ||
| 822 | 819 | ||
| 823 | if (mixer_res->sclk_hdmi) | 820 | if (mixer_ctx->has_sclk) { |
| 824 | clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); | 821 | mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); |
| 822 | if (IS_ERR(mixer_res->sclk_mixer)) { | ||
| 823 | dev_err(dev, "failed to get clock 'sclk_mixer'\n"); | ||
| 824 | return -ENODEV; | ||
| 825 | } | ||
| 826 | mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer"); | ||
| 827 | if (IS_ERR(mixer_res->mout_mixer)) { | ||
| 828 | dev_err(dev, "failed to get clock 'mout_mixer'\n"); | ||
| 829 | return -ENODEV; | ||
| 830 | } | ||
| 831 | |||
| 832 | if (mixer_res->sclk_hdmi && mixer_res->mout_mixer) | ||
| 833 | clk_set_parent(mixer_res->mout_mixer, | ||
| 834 | mixer_res->sclk_hdmi); | ||
| 835 | } | ||
| 825 | 836 | ||
| 826 | res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); | 837 | res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); |
| 827 | if (res == NULL) { | 838 | if (res == NULL) { |
| @@ -1082,7 +1093,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) | |||
| 1082 | clk_prepare_enable(res->mixer); | 1093 | clk_prepare_enable(res->mixer); |
| 1083 | if (ctx->vp_enabled) { | 1094 | if (ctx->vp_enabled) { |
| 1084 | clk_prepare_enable(res->vp); | 1095 | clk_prepare_enable(res->vp); |
| 1085 | clk_prepare_enable(res->sclk_mixer); | 1096 | if (ctx->has_sclk) |
| 1097 | clk_prepare_enable(res->sclk_mixer); | ||
| 1086 | } | 1098 | } |
| 1087 | 1099 | ||
| 1088 | mutex_lock(&ctx->mixer_mutex); | 1100 | mutex_lock(&ctx->mixer_mutex); |
| @@ -1121,7 +1133,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) | |||
| 1121 | clk_disable_unprepare(res->mixer); | 1133 | clk_disable_unprepare(res->mixer); |
| 1122 | if (ctx->vp_enabled) { | 1134 | if (ctx->vp_enabled) { |
| 1123 | clk_disable_unprepare(res->vp); | 1135 | clk_disable_unprepare(res->vp); |
| 1124 | clk_disable_unprepare(res->sclk_mixer); | 1136 | if (ctx->has_sclk) |
| 1137 | clk_disable_unprepare(res->sclk_mixer); | ||
| 1125 | } | 1138 | } |
| 1126 | 1139 | ||
| 1127 | pm_runtime_put_sync(ctx->dev); | 1140 | pm_runtime_put_sync(ctx->dev); |
| @@ -1189,9 +1202,15 @@ static struct mixer_drv_data exynos5250_mxr_drv_data = { | |||
| 1189 | .is_vp_enabled = 0, | 1202 | .is_vp_enabled = 0, |
| 1190 | }; | 1203 | }; |
| 1191 | 1204 | ||
| 1205 | static struct mixer_drv_data exynos4212_mxr_drv_data = { | ||
| 1206 | .version = MXR_VER_0_0_0_16, | ||
| 1207 | .is_vp_enabled = 1, | ||
| 1208 | }; | ||
| 1209 | |||
| 1192 | static struct mixer_drv_data exynos4210_mxr_drv_data = { | 1210 | static struct mixer_drv_data exynos4210_mxr_drv_data = { |
| 1193 | .version = MXR_VER_0_0_0_16, | 1211 | .version = MXR_VER_0_0_0_16, |
| 1194 | .is_vp_enabled = 1, | 1212 | .is_vp_enabled = 1, |
| 1213 | .has_sclk = 1, | ||
| 1195 | }; | 1214 | }; |
| 1196 | 1215 | ||
| 1197 | static struct platform_device_id mixer_driver_types[] = { | 1216 | static struct platform_device_id mixer_driver_types[] = { |
| @@ -1208,6 +1227,12 @@ static struct platform_device_id mixer_driver_types[] = { | |||
| 1208 | 1227 | ||
| 1209 | static struct of_device_id mixer_match_types[] = { | 1228 | static struct of_device_id mixer_match_types[] = { |
| 1210 | { | 1229 | { |
| 1230 | .compatible = "samsung,exynos4210-mixer", | ||
| 1231 | .data = &exynos4210_mxr_drv_data, | ||
| 1232 | }, { | ||
| 1233 | .compatible = "samsung,exynos4212-mixer", | ||
| 1234 | .data = &exynos4212_mxr_drv_data, | ||
| 1235 | }, { | ||
| 1211 | .compatible = "samsung,exynos5-mixer", | 1236 | .compatible = "samsung,exynos5-mixer", |
| 1212 | .data = &exynos5250_mxr_drv_data, | 1237 | .data = &exynos5250_mxr_drv_data, |
| 1213 | }, { | 1238 | }, { |
| @@ -1220,6 +1245,7 @@ static struct of_device_id mixer_match_types[] = { | |||
| 1220 | /* end node */ | 1245 | /* end node */ |
| 1221 | } | 1246 | } |
| 1222 | }; | 1247 | }; |
| 1248 | MODULE_DEVICE_TABLE(of, mixer_match_types); | ||
| 1223 | 1249 | ||
| 1224 | static int mixer_bind(struct device *dev, struct device *manager, void *data) | 1250 | static int mixer_bind(struct device *dev, struct device *manager, void *data) |
| 1225 | { | 1251 | { |
| @@ -1251,6 +1277,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) | |||
| 1251 | ctx->pdev = pdev; | 1277 | ctx->pdev = pdev; |
| 1252 | ctx->dev = dev; | 1278 | ctx->dev = dev; |
| 1253 | ctx->vp_enabled = drv->is_vp_enabled; | 1279 | ctx->vp_enabled = drv->is_vp_enabled; |
| 1280 | ctx->has_sclk = drv->has_sclk; | ||
| 1254 | ctx->mxr_ver = drv->version; | 1281 | ctx->mxr_ver = drv->version; |
| 1255 | init_waitqueue_head(&ctx->wait_vsync_queue); | 1282 | init_waitqueue_head(&ctx->wait_vsync_queue); |
| 1256 | atomic_set(&ctx->wait_vsync_event, 0); | 1283 | atomic_set(&ctx->wait_vsync_event, 0); |
