diff options
author | Dave Airlie <airlied@redhat.com> | 2012-12-16 00:49:46 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-12-16 00:49:46 -0500 |
commit | 2f3f24061c5c489074ad492bf694a5a76ebd8fc5 (patch) | |
tree | a02e00a7e98a4fa543b1e7fc4eda2fbd62d16b6d /drivers/gpu/drm/exynos/exynos_mixer.c | |
parent | 652a187664902399d34f5b3a084fdbb51b2ca12f (diff) | |
parent | f2646380655b32481b5e76c666e1793dfef184bd (diff) |
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Inki writes:
"- add dmabuf attach/detach feature
. This patch would resolve performance deterioration issue
when v4l2-based driver is using the buffer imported from gem.
- drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute
. With gem allocation, kernel space mapping isn't allocated and
also physical pages aren't mapped with the kernel space.
The physical pages are mapped with kernel space though vmap
function only for console framebuffer.
- add the below two patches I missed.
drm: exynos: moved exynos drm device registration to drm driver
drm: exynos: moved exynos drm hdmi device registration to drm driver
- add IPP subsystem framework and its-based device drivers.
. This patch set includes fimc, rotator and gsc drivers to perform
image scaling, rotation and color space conversion.
- add runtime pm support to hdmi driver.
- And fixups and cleanups."
* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (30 commits)
drm/exynos: add gsc ipp driver
drm/exynos: add rotator ipp driver
drm/exynos: add fimc ipp driver
drm/exynos: add iommu support for ipp
drm/exynos: add ipp subsystem
drm/exynos: support device tree for fimd
drm/exynos: support extended screen coordinate of fimd
drm/exynos: fix x, y coordinates for right bottom pixel
drm/exynos: fix fb offset calculation for plane
drm/exynos: hdmi: Fix potential NULL pointer dereference error
drm/exynos: hdmi: Add CONFIG_OF and use of_match_ptr() macro
drm/exynos: add support for hdmiphy power control for exynos5
drm/exynos: add runtime pm support for mixer
drm/exynos: added runtime pm support for hdmi
drm/exynos: fix allocation and cache mapping type
drm/exynos: reorder framebuffer init sequence
drm/exynos/iommu: fix return value check in drm_create_iommu_mapping()
drm/exynos: remove unused vaddr member
drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute
drm/exynos: add exception codes to exynos_drm_fbdev_create()
...
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_mixer.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 297 |
1 files changed, 204 insertions, 93 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 40a6e1906fbb..21db89530fc7 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -42,9 +42,7 @@ | |||
42 | 42 | ||
43 | struct hdmi_win_data { | 43 | struct hdmi_win_data { |
44 | dma_addr_t dma_addr; | 44 | dma_addr_t dma_addr; |
45 | void __iomem *vaddr; | ||
46 | dma_addr_t chroma_dma_addr; | 45 | dma_addr_t chroma_dma_addr; |
47 | void __iomem *chroma_vaddr; | ||
48 | uint32_t pixel_format; | 46 | uint32_t pixel_format; |
49 | unsigned int bpp; | 47 | unsigned int bpp; |
50 | unsigned int crtc_x; | 48 | unsigned int crtc_x; |
@@ -60,6 +58,8 @@ struct hdmi_win_data { | |||
60 | unsigned int mode_width; | 58 | unsigned int mode_width; |
61 | unsigned int mode_height; | 59 | unsigned int mode_height; |
62 | unsigned int scan_flags; | 60 | unsigned int scan_flags; |
61 | bool enabled; | ||
62 | bool resume; | ||
63 | }; | 63 | }; |
64 | 64 | ||
65 | struct mixer_resources { | 65 | struct mixer_resources { |
@@ -93,6 +93,8 @@ struct mixer_context { | |||
93 | struct hdmi_win_data win_data[MIXER_WIN_NR]; | 93 | struct hdmi_win_data win_data[MIXER_WIN_NR]; |
94 | enum mixer_version_id mxr_ver; | 94 | enum mixer_version_id mxr_ver; |
95 | void *parent_ctx; | 95 | void *parent_ctx; |
96 | wait_queue_head_t wait_vsync_queue; | ||
97 | atomic_t wait_vsync_event; | ||
96 | }; | 98 | }; |
97 | 99 | ||
98 | struct mixer_drv_data { | 100 | struct mixer_drv_data { |
@@ -686,60 +688,6 @@ static int mixer_iommu_on(void *ctx, bool enable) | |||
686 | return 0; | 688 | return 0; |
687 | } | 689 | } |
688 | 690 | ||
689 | static void mixer_poweron(struct mixer_context *ctx) | ||
690 | { | ||
691 | struct mixer_resources *res = &ctx->mixer_res; | ||
692 | |||
693 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
694 | |||
695 | mutex_lock(&ctx->mixer_mutex); | ||
696 | if (ctx->powered) { | ||
697 | mutex_unlock(&ctx->mixer_mutex); | ||
698 | return; | ||
699 | } | ||
700 | ctx->powered = true; | ||
701 | mutex_unlock(&ctx->mixer_mutex); | ||
702 | |||
703 | pm_runtime_get_sync(ctx->dev); | ||
704 | |||
705 | clk_enable(res->mixer); | ||
706 | if (ctx->vp_enabled) { | ||
707 | clk_enable(res->vp); | ||
708 | clk_enable(res->sclk_mixer); | ||
709 | } | ||
710 | |||
711 | mixer_reg_write(res, MXR_INT_EN, ctx->int_en); | ||
712 | mixer_win_reset(ctx); | ||
713 | } | ||
714 | |||
715 | static void mixer_poweroff(struct mixer_context *ctx) | ||
716 | { | ||
717 | struct mixer_resources *res = &ctx->mixer_res; | ||
718 | |||
719 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
720 | |||
721 | mutex_lock(&ctx->mixer_mutex); | ||
722 | if (!ctx->powered) | ||
723 | goto out; | ||
724 | mutex_unlock(&ctx->mixer_mutex); | ||
725 | |||
726 | ctx->int_en = mixer_reg_read(res, MXR_INT_EN); | ||
727 | |||
728 | clk_disable(res->mixer); | ||
729 | if (ctx->vp_enabled) { | ||
730 | clk_disable(res->vp); | ||
731 | clk_disable(res->sclk_mixer); | ||
732 | } | ||
733 | |||
734 | pm_runtime_put_sync(ctx->dev); | ||
735 | |||
736 | mutex_lock(&ctx->mixer_mutex); | ||
737 | ctx->powered = false; | ||
738 | |||
739 | out: | ||
740 | mutex_unlock(&ctx->mixer_mutex); | ||
741 | } | ||
742 | |||
743 | static int mixer_enable_vblank(void *ctx, int pipe) | 691 | static int mixer_enable_vblank(void *ctx, int pipe) |
744 | { | 692 | { |
745 | struct mixer_context *mixer_ctx = ctx; | 693 | struct mixer_context *mixer_ctx = ctx; |
@@ -767,39 +715,6 @@ static void mixer_disable_vblank(void *ctx) | |||
767 | mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); | 715 | mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); |
768 | } | 716 | } |
769 | 717 | ||
770 | static void mixer_dpms(void *ctx, int mode) | ||
771 | { | ||
772 | struct mixer_context *mixer_ctx = ctx; | ||
773 | |||
774 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
775 | |||
776 | switch (mode) { | ||
777 | case DRM_MODE_DPMS_ON: | ||
778 | mixer_poweron(mixer_ctx); | ||
779 | break; | ||
780 | case DRM_MODE_DPMS_STANDBY: | ||
781 | case DRM_MODE_DPMS_SUSPEND: | ||
782 | case DRM_MODE_DPMS_OFF: | ||
783 | mixer_poweroff(mixer_ctx); | ||
784 | break; | ||
785 | default: | ||
786 | DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); | ||
787 | break; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | static void mixer_wait_for_vblank(void *ctx) | ||
792 | { | ||
793 | struct mixer_context *mixer_ctx = ctx; | ||
794 | struct mixer_resources *res = &mixer_ctx->mixer_res; | ||
795 | int ret; | ||
796 | |||
797 | ret = wait_for((mixer_reg_read(res, MXR_INT_STATUS) & | ||
798 | MXR_INT_STATUS_VSYNC), 50); | ||
799 | if (ret < 0) | ||
800 | DRM_DEBUG_KMS("vblank wait timed out.\n"); | ||
801 | } | ||
802 | |||
803 | static void mixer_win_mode_set(void *ctx, | 718 | static void mixer_win_mode_set(void *ctx, |
804 | struct exynos_drm_overlay *overlay) | 719 | struct exynos_drm_overlay *overlay) |
805 | { | 720 | { |
@@ -832,9 +747,7 @@ static void mixer_win_mode_set(void *ctx, | |||
832 | win_data = &mixer_ctx->win_data[win]; | 747 | win_data = &mixer_ctx->win_data[win]; |
833 | 748 | ||
834 | win_data->dma_addr = overlay->dma_addr[0]; | 749 | win_data->dma_addr = overlay->dma_addr[0]; |
835 | win_data->vaddr = overlay->vaddr[0]; | ||
836 | win_data->chroma_dma_addr = overlay->dma_addr[1]; | 750 | win_data->chroma_dma_addr = overlay->dma_addr[1]; |
837 | win_data->chroma_vaddr = overlay->vaddr[1]; | ||
838 | win_data->pixel_format = overlay->pixel_format; | 751 | win_data->pixel_format = overlay->pixel_format; |
839 | win_data->bpp = overlay->bpp; | 752 | win_data->bpp = overlay->bpp; |
840 | 753 | ||
@@ -866,6 +779,8 @@ static void mixer_win_commit(void *ctx, int win) | |||
866 | vp_video_buffer(mixer_ctx, win); | 779 | vp_video_buffer(mixer_ctx, win); |
867 | else | 780 | else |
868 | mixer_graph_buffer(mixer_ctx, win); | 781 | mixer_graph_buffer(mixer_ctx, win); |
782 | |||
783 | mixer_ctx->win_data[win].enabled = true; | ||
869 | } | 784 | } |
870 | 785 | ||
871 | static void mixer_win_disable(void *ctx, int win) | 786 | static void mixer_win_disable(void *ctx, int win) |
@@ -876,6 +791,14 @@ static void mixer_win_disable(void *ctx, int win) | |||
876 | 791 | ||
877 | DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); | 792 | DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); |
878 | 793 | ||
794 | mutex_lock(&mixer_ctx->mixer_mutex); | ||
795 | if (!mixer_ctx->powered) { | ||
796 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
797 | mixer_ctx->win_data[win].resume = false; | ||
798 | return; | ||
799 | } | ||
800 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
801 | |||
879 | spin_lock_irqsave(&res->reg_slock, flags); | 802 | spin_lock_irqsave(&res->reg_slock, flags); |
880 | mixer_vsync_set_update(mixer_ctx, false); | 803 | mixer_vsync_set_update(mixer_ctx, false); |
881 | 804 | ||
@@ -883,6 +806,133 @@ static void mixer_win_disable(void *ctx, int win) | |||
883 | 806 | ||
884 | mixer_vsync_set_update(mixer_ctx, true); | 807 | mixer_vsync_set_update(mixer_ctx, true); |
885 | spin_unlock_irqrestore(&res->reg_slock, flags); | 808 | spin_unlock_irqrestore(&res->reg_slock, flags); |
809 | |||
810 | mixer_ctx->win_data[win].enabled = false; | ||
811 | } | ||
812 | |||
813 | static void mixer_wait_for_vblank(void *ctx) | ||
814 | { | ||
815 | struct mixer_context *mixer_ctx = ctx; | ||
816 | |||
817 | mutex_lock(&mixer_ctx->mixer_mutex); | ||
818 | if (!mixer_ctx->powered) { | ||
819 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
820 | return; | ||
821 | } | ||
822 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
823 | |||
824 | atomic_set(&mixer_ctx->wait_vsync_event, 1); | ||
825 | |||
826 | /* | ||
827 | * wait for MIXER to signal VSYNC interrupt or return after | ||
828 | * timeout which is set to 50ms (refresh rate of 20). | ||
829 | */ | ||
830 | if (!wait_event_timeout(mixer_ctx->wait_vsync_queue, | ||
831 | !atomic_read(&mixer_ctx->wait_vsync_event), | ||
832 | DRM_HZ/20)) | ||
833 | DRM_DEBUG_KMS("vblank wait timed out.\n"); | ||
834 | } | ||
835 | |||
836 | static void mixer_window_suspend(struct mixer_context *ctx) | ||
837 | { | ||
838 | struct hdmi_win_data *win_data; | ||
839 | int i; | ||
840 | |||
841 | for (i = 0; i < MIXER_WIN_NR; i++) { | ||
842 | win_data = &ctx->win_data[i]; | ||
843 | win_data->resume = win_data->enabled; | ||
844 | mixer_win_disable(ctx, i); | ||
845 | } | ||
846 | mixer_wait_for_vblank(ctx); | ||
847 | } | ||
848 | |||
849 | static void mixer_window_resume(struct mixer_context *ctx) | ||
850 | { | ||
851 | struct hdmi_win_data *win_data; | ||
852 | int i; | ||
853 | |||
854 | for (i = 0; i < MIXER_WIN_NR; i++) { | ||
855 | win_data = &ctx->win_data[i]; | ||
856 | win_data->enabled = win_data->resume; | ||
857 | win_data->resume = false; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | static void mixer_poweron(struct mixer_context *ctx) | ||
862 | { | ||
863 | struct mixer_resources *res = &ctx->mixer_res; | ||
864 | |||
865 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
866 | |||
867 | mutex_lock(&ctx->mixer_mutex); | ||
868 | if (ctx->powered) { | ||
869 | mutex_unlock(&ctx->mixer_mutex); | ||
870 | return; | ||
871 | } | ||
872 | ctx->powered = true; | ||
873 | mutex_unlock(&ctx->mixer_mutex); | ||
874 | |||
875 | clk_enable(res->mixer); | ||
876 | if (ctx->vp_enabled) { | ||
877 | clk_enable(res->vp); | ||
878 | clk_enable(res->sclk_mixer); | ||
879 | } | ||
880 | |||
881 | mixer_reg_write(res, MXR_INT_EN, ctx->int_en); | ||
882 | mixer_win_reset(ctx); | ||
883 | |||
884 | mixer_window_resume(ctx); | ||
885 | } | ||
886 | |||
887 | static void mixer_poweroff(struct mixer_context *ctx) | ||
888 | { | ||
889 | struct mixer_resources *res = &ctx->mixer_res; | ||
890 | |||
891 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
892 | |||
893 | mutex_lock(&ctx->mixer_mutex); | ||
894 | if (!ctx->powered) | ||
895 | goto out; | ||
896 | mutex_unlock(&ctx->mixer_mutex); | ||
897 | |||
898 | mixer_window_suspend(ctx); | ||
899 | |||
900 | ctx->int_en = mixer_reg_read(res, MXR_INT_EN); | ||
901 | |||
902 | clk_disable(res->mixer); | ||
903 | if (ctx->vp_enabled) { | ||
904 | clk_disable(res->vp); | ||
905 | clk_disable(res->sclk_mixer); | ||
906 | } | ||
907 | |||
908 | mutex_lock(&ctx->mixer_mutex); | ||
909 | ctx->powered = false; | ||
910 | |||
911 | out: | ||
912 | mutex_unlock(&ctx->mixer_mutex); | ||
913 | } | ||
914 | |||
915 | static void mixer_dpms(void *ctx, int mode) | ||
916 | { | ||
917 | struct mixer_context *mixer_ctx = ctx; | ||
918 | |||
919 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
920 | |||
921 | switch (mode) { | ||
922 | case DRM_MODE_DPMS_ON: | ||
923 | if (pm_runtime_suspended(mixer_ctx->dev)) | ||
924 | pm_runtime_get_sync(mixer_ctx->dev); | ||
925 | break; | ||
926 | case DRM_MODE_DPMS_STANDBY: | ||
927 | case DRM_MODE_DPMS_SUSPEND: | ||
928 | case DRM_MODE_DPMS_OFF: | ||
929 | if (!pm_runtime_suspended(mixer_ctx->dev)) | ||
930 | pm_runtime_put_sync(mixer_ctx->dev); | ||
931 | break; | ||
932 | default: | ||
933 | DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); | ||
934 | break; | ||
935 | } | ||
886 | } | 936 | } |
887 | 937 | ||
888 | static struct exynos_mixer_ops mixer_ops = { | 938 | static struct exynos_mixer_ops mixer_ops = { |
@@ -890,10 +940,10 @@ static struct exynos_mixer_ops mixer_ops = { | |||
890 | .iommu_on = mixer_iommu_on, | 940 | .iommu_on = mixer_iommu_on, |
891 | .enable_vblank = mixer_enable_vblank, | 941 | .enable_vblank = mixer_enable_vblank, |
892 | .disable_vblank = mixer_disable_vblank, | 942 | .disable_vblank = mixer_disable_vblank, |
943 | .wait_for_vblank = mixer_wait_for_vblank, | ||
893 | .dpms = mixer_dpms, | 944 | .dpms = mixer_dpms, |
894 | 945 | ||
895 | /* overlay */ | 946 | /* overlay */ |
896 | .wait_for_vblank = mixer_wait_for_vblank, | ||
897 | .win_mode_set = mixer_win_mode_set, | 947 | .win_mode_set = mixer_win_mode_set, |
898 | .win_commit = mixer_win_commit, | 948 | .win_commit = mixer_win_commit, |
899 | .win_disable = mixer_win_disable, | 949 | .win_disable = mixer_win_disable, |
@@ -957,6 +1007,12 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) | |||
957 | 1007 | ||
958 | drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe); | 1008 | drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe); |
959 | mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe); | 1009 | mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe); |
1010 | |||
1011 | /* set wait vsync event to zero and wake up queue. */ | ||
1012 | if (atomic_read(&ctx->wait_vsync_event)) { | ||
1013 | atomic_set(&ctx->wait_vsync_event, 0); | ||
1014 | DRM_WAKEUP(&ctx->wait_vsync_queue); | ||
1015 | } | ||
960 | } | 1016 | } |
961 | 1017 | ||
962 | out: | 1018 | out: |
@@ -1139,6 +1195,8 @@ static int __devinit mixer_probe(struct platform_device *pdev) | |||
1139 | drm_hdmi_ctx->ctx = (void *)ctx; | 1195 | drm_hdmi_ctx->ctx = (void *)ctx; |
1140 | ctx->vp_enabled = drv->is_vp_enabled; | 1196 | ctx->vp_enabled = drv->is_vp_enabled; |
1141 | ctx->mxr_ver = drv->version; | 1197 | ctx->mxr_ver = drv->version; |
1198 | DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue); | ||
1199 | atomic_set(&ctx->wait_vsync_event, 0); | ||
1142 | 1200 | ||
1143 | platform_set_drvdata(pdev, drm_hdmi_ctx); | 1201 | platform_set_drvdata(pdev, drm_hdmi_ctx); |
1144 | 1202 | ||
@@ -1189,13 +1247,66 @@ static int mixer_suspend(struct device *dev) | |||
1189 | struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); | 1247 | struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); |
1190 | struct mixer_context *ctx = drm_hdmi_ctx->ctx; | 1248 | struct mixer_context *ctx = drm_hdmi_ctx->ctx; |
1191 | 1249 | ||
1250 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
1251 | |||
1252 | if (pm_runtime_suspended(dev)) { | ||
1253 | DRM_DEBUG_KMS("%s : Already suspended\n", __func__); | ||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1192 | mixer_poweroff(ctx); | 1257 | mixer_poweroff(ctx); |
1193 | 1258 | ||
1194 | return 0; | 1259 | return 0; |
1195 | } | 1260 | } |
1261 | |||
1262 | static int mixer_resume(struct device *dev) | ||
1263 | { | ||
1264 | struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); | ||
1265 | struct mixer_context *ctx = drm_hdmi_ctx->ctx; | ||
1266 | |||
1267 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
1268 | |||
1269 | if (!pm_runtime_suspended(dev)) { | ||
1270 | DRM_DEBUG_KMS("%s : Already resumed\n", __func__); | ||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | mixer_poweron(ctx); | ||
1275 | |||
1276 | return 0; | ||
1277 | } | ||
1196 | #endif | 1278 | #endif |
1197 | 1279 | ||
1198 | static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL); | 1280 | #ifdef CONFIG_PM_RUNTIME |
1281 | static int mixer_runtime_suspend(struct device *dev) | ||
1282 | { | ||
1283 | struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); | ||
1284 | struct mixer_context *ctx = drm_hdmi_ctx->ctx; | ||
1285 | |||
1286 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
1287 | |||
1288 | mixer_poweroff(ctx); | ||
1289 | |||
1290 | return 0; | ||
1291 | } | ||
1292 | |||
1293 | static int mixer_runtime_resume(struct device *dev) | ||
1294 | { | ||
1295 | struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); | ||
1296 | struct mixer_context *ctx = drm_hdmi_ctx->ctx; | ||
1297 | |||
1298 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | ||
1299 | |||
1300 | mixer_poweron(ctx); | ||
1301 | |||
1302 | return 0; | ||
1303 | } | ||
1304 | #endif | ||
1305 | |||
1306 | static const struct dev_pm_ops mixer_pm_ops = { | ||
1307 | SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume) | ||
1308 | SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL) | ||
1309 | }; | ||
1199 | 1310 | ||
1200 | struct platform_driver mixer_driver = { | 1311 | struct platform_driver mixer_driver = { |
1201 | .driver = { | 1312 | .driver = { |