Commit 1fae6dfe authored by Dave Airlie's avatar Dave Airlie

Merge branch 'exynos-drm-next' of...

Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next

   This pull request includes i80 interface support, module auto-loading
   ipp consolidation, and trivail fixups and cleanups.

Summary:
- Add i80 interface support. For this, we added some features to
  Exynos drm framework, which don't affect any other SoC and common
  framework because they are specific to Exynos drm.
- Add module auto-loading support. For this, sub drivers of Exynos drm
  exports their of match tables to userspace. This allows modules to be
  loaded automatically based on devicetree information
- Consolidate ipp driver. This patch just just includes cleanups and
  a littl bit refactoring codes.

If there is any problem, please kindly let me know.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (38 commits)
  drm/exynos: g2d: let exynos_g2d_get_ver_ioctl fail
  drm/exynos: g2d: make ioctls more robust
  drm/exynos: hdmi: add null check for hdmiphy_port
  drm/exynos: control blending of mixer graphic layer 0
  drm/exynos: Add MODULE_DEVICE_TABLE entries for various components
  Subject: Revert "drm/exynos: remove MODULE_DEVICE_TABLE definitions"
  Subject: Revert "drm/exynos: fix module build error"
  drm/exynos/ipp: simplify ipp_find_driver
  drm/exynos/ipp: simplify ipp_create_id
  drm/exynos/ipp: remove redundant messages
  drm/exynos/ipp: simplify ipp_find_obj
  drm/exynos/ipp: remove useless registration checks
  drm/exynos/ipp: simplify memory check function
  drm/exynos/ipp: remove incorrect checks of list_first_entry result
  drm/exynos/ipp: remove temporary variable
  drm/exynos/ipp: correct address type
  drm/exynos/ipp: remove struct exynos_drm_ipp_private
  drm/exynos/ipp: remove unused field from exynos_drm_ipp_private
  drm/exynos/ipp: remove type casting
  drm/exynos: g2d: add exynos4212 as a compatible device.
  ...
parents 08d645c1 ef7ce055
Exynos MIPI DSI Master Exynos MIPI DSI Master
Required properties: Required properties:
- compatible: "samsung,exynos4210-mipi-dsi" - compatible: value should be one of the following
"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
- reg: physical base address and length of the registers set for the device - reg: physical base address and length of the registers set for the device
- interrupts: should contain DSI interrupt - interrupts: should contain DSI interrupt
- clocks: list of clock specifiers, must contain an entry for each required - clocks: list of clock specifiers, must contain an entry for each required
......
...@@ -4,8 +4,9 @@ Required properties: ...@@ -4,8 +4,9 @@ Required properties:
- compatible: value should be one of the following: - compatible: value should be one of the following:
1) "samsung,exynos5-mixer" <DEPRECATED> 1) "samsung,exynos5-mixer" <DEPRECATED>
2) "samsung,exynos4210-mixer" 2) "samsung,exynos4210-mixer"
3) "samsung,exynos5250-mixer" 3) "samsung,exynos4212-mixer"
4) "samsung,exynos5420-mixer" 4) "samsung,exynos5250-mixer"
5) "samsung,exynos5420-mixer"
- reg: physical base address of the mixer and length of memory mapped - reg: physical base address of the mixer and length of memory mapped
region. region.
......
...@@ -44,6 +44,34 @@ Optional Properties: ...@@ -44,6 +44,34 @@ Optional Properties:
- display-timings: timing settings for FIMD, as described in document [1]. - display-timings: timing settings for FIMD, as described in document [1].
Can be used in case timings cannot be provided otherwise Can be used in case timings cannot be provided otherwise
or to override timings provided by the panel. or to override timings provided by the panel.
- samsung,sysreg: handle to syscon used to control the system registers
- i80-if-timings: timing configuration for lcd i80 interface support.
- cs-setup: clock cycles for the active period of address signal is enabled
until chip select is enabled.
If not specified, the default value(0) will be used.
- wr-setup: clock cycles for the active period of CS signal is enabled until
write signal is enabled.
If not specified, the default value(0) will be used.
- wr-active: clock cycles for the active period of CS is enabled.
If not specified, the default value(1) will be used.
- wr-hold: clock cycles for the active period of CS is disabled until write
signal is disabled.
If not specified, the default value(0) will be used.
The parameters are defined as:
VCLK(internal) __|??????|_____|??????|_____|??????|_____|??????|_____|??
: : : : :
Address Output --:<XXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XX
| cs-setup+1 | : : :
|<---------->| : : :
Chip Select ???????????????|____________:____________:____________|??
| wr-setup+1 | | wr-hold+1 |
|<---------->| |<---------->|
Write Enable ????????????????????????????|____________|???????????????
| wr-active+1|
|<---------->|
Video Data ----------------------------<XXXXXXXXXXXXXXXXXXXXXXXXX>--
The device node can contain 'port' child nodes according to the bindings defined The device node can contain 'port' child nodes according to the bindings defined
in [2]. The following are properties specific to those nodes: in [2]. The following are properties specific to those nodes:
......
...@@ -608,6 +608,7 @@ fimd: fimd@11c00000 { ...@@ -608,6 +608,7 @@ fimd: fimd@11c00000 {
clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>; clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
clock-names = "sclk_fimd", "fimd"; clock-names = "sclk_fimd", "fimd";
samsung,power-domain = <&pd_lcd0>; samsung,power-domain = <&pd_lcd0>;
samsung,sysreg = <&sys_reg>;
status = "disabled"; status = "disabled";
}; };
}; };
...@@ -87,6 +87,7 @@ fimd@14400000 { ...@@ -87,6 +87,7 @@ fimd@14400000 {
reg = <0x14400000 0x40000>; reg = <0x14400000 0x40000>;
interrupt-names = "fifo", "vsync", "lcd_sys"; interrupt-names = "fifo", "vsync", "lcd_sys";
interrupts = <18 4>, <18 5>, <18 6>; interrupts = <18 4>, <18 5>, <18 6>;
samsung,sysreg = <&sysreg_system_controller>;
status = "disabled"; status = "disabled";
}; };
......
...@@ -517,6 +517,26 @@ dp: dp-controller@145B0000 { ...@@ -517,6 +517,26 @@ dp: dp-controller@145B0000 {
phy-names = "dp"; phy-names = "dp";
}; };
mipi_phy: video-phy@10040714 {
compatible = "samsung,s5pv210-mipi-video-phy";
reg = <0x10040714 12>;
#phy-cells = <1>;
};
dsi@14500000 {
compatible = "samsung,exynos5410-mipi-dsi";
reg = <0x14500000 0x10000>;
interrupts = <0 82 0>;
samsung,power-domain = <&disp_pd>;
phys = <&mipi_phy 1>;
phy-names = "dsim";
clocks = <&clock CLK_DSIM1>, <&clock CLK_SCLK_MIPI1>;
clock-names = "bus_clk", "pll_clk";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
fimd: fimd@14400000 { fimd: fimd@14400000 {
samsung,power-domain = <&disp_pd>; samsung,power-domain = <&disp_pd>;
clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>; clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
......
...@@ -28,6 +28,7 @@ config DRM_EXYNOS_FIMD ...@@ -28,6 +28,7 @@ config DRM_EXYNOS_FIMD
bool "Exynos DRM FIMD" bool "Exynos DRM FIMD"
depends on DRM_EXYNOS && !FB_S3C depends on DRM_EXYNOS && !FB_S3C
select FB_MODE_HELPERS select FB_MODE_HELPERS
select MFD_SYSCON
help help
Choose this option if you want to use Exynos FIMD for DRM. Choose this option if you want to use Exynos FIMD for DRM.
......
...@@ -1376,6 +1376,7 @@ static const struct of_device_id exynos_dp_match[] = { ...@@ -1376,6 +1376,7 @@ static const struct of_device_id exynos_dp_match[] = {
{ .compatible = "samsung,exynos5-dp" }, { .compatible = "samsung,exynos5-dp" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, exynos_dp_match);
struct platform_driver dp_driver = { struct platform_driver dp_driver = {
.probe = exynos_dp_probe, .probe = exynos_dp_probe,
...@@ -1390,4 +1391,4 @@ struct platform_driver dp_driver = { ...@@ -1390,4 +1391,4 @@ struct platform_driver dp_driver = {
MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
MODULE_DESCRIPTION("Samsung SoC DP Driver"); MODULE_DESCRIPTION("Samsung SoC DP Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
...@@ -69,8 +69,10 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -69,8 +69,10 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
if (mode > DRM_MODE_DPMS_ON) { if (mode > DRM_MODE_DPMS_ON) {
/* wait for the completion of page flip. */ /* wait for the completion of page flip. */
wait_event(exynos_crtc->pending_flip_queue, if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
atomic_read(&exynos_crtc->pending_flip) == 0); !atomic_read(&exynos_crtc->pending_flip),
HZ/20))
atomic_set(&exynos_crtc->pending_flip, 0);
drm_vblank_off(crtc->dev, exynos_crtc->pipe); drm_vblank_off(crtc->dev, exynos_crtc->pipe);
} }
...@@ -259,6 +261,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, ...@@ -259,6 +261,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
spin_lock_irq(&dev->event_lock); spin_lock_irq(&dev->event_lock);
drm_vblank_put(dev, exynos_crtc->pipe); drm_vblank_put(dev, exynos_crtc->pipe);
list_del(&event->base.link); list_del(&event->base.link);
atomic_set(&exynos_crtc->pending_flip, 0);
spin_unlock_irq(&dev->event_lock); spin_unlock_irq(&dev->event_lock);
goto out; goto out;
...@@ -508,3 +511,11 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, ...@@ -508,3 +511,11 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
return -EPERM; return -EPERM;
} }
void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
{
struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
if (manager->ops->te_handler)
manager->ops->te_handler(manager);
}
...@@ -36,4 +36,11 @@ void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos); ...@@ -36,4 +36,11 @@ void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
unsigned int out_type); unsigned int out_type);
/*
* This function calls the crtc device(manager)'s te_handler() callback
* to trigger to transfer video image at the tearing effect synchronization
* signal.
*/
void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
#endif #endif
...@@ -358,7 +358,7 @@ static int exynos_drm_sys_suspend(struct device *dev) ...@@ -358,7 +358,7 @@ static int exynos_drm_sys_suspend(struct device *dev)
struct drm_device *drm_dev = dev_get_drvdata(dev); struct drm_device *drm_dev = dev_get_drvdata(dev);
pm_message_t message; pm_message_t message;
if (pm_runtime_suspended(dev)) if (pm_runtime_suspended(dev) || !drm_dev)
return 0; return 0;
message.event = PM_EVENT_SUSPEND; message.event = PM_EVENT_SUSPEND;
...@@ -369,7 +369,7 @@ static int exynos_drm_sys_resume(struct device *dev) ...@@ -369,7 +369,7 @@ static int exynos_drm_sys_resume(struct device *dev)
{ {
struct drm_device *drm_dev = dev_get_drvdata(dev); struct drm_device *drm_dev = dev_get_drvdata(dev);
if (pm_runtime_suspended(dev)) if (pm_runtime_suspended(dev) || !drm_dev)
return 0; return 0;
return exynos_drm_resume(drm_dev); return exynos_drm_resume(drm_dev);
......
...@@ -186,6 +186,8 @@ struct exynos_drm_display { ...@@ -186,6 +186,8 @@ struct exynos_drm_display {
* @win_commit: apply hardware specific overlay data to registers. * @win_commit: apply hardware specific overlay data to registers.
* @win_enable: enable hardware specific overlay. * @win_enable: enable hardware specific overlay.
* @win_disable: disable hardware specific overlay. * @win_disable: disable hardware specific overlay.
* @te_handler: trigger to transfer video image at the tearing effect
* synchronization signal if there is a page flip request.
*/ */
struct exynos_drm_manager; struct exynos_drm_manager;
struct exynos_drm_manager_ops { struct exynos_drm_manager_ops {
...@@ -204,6 +206,7 @@ struct exynos_drm_manager_ops { ...@@ -204,6 +206,7 @@ struct exynos_drm_manager_ops {
void (*win_commit)(struct exynos_drm_manager *mgr, int zpos); void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
void (*win_enable)(struct exynos_drm_manager *mgr, int zpos); void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
void (*win_disable)(struct exynos_drm_manager *mgr, int zpos); void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
void (*te_handler)(struct exynos_drm_manager *mgr);
}; };
/* /*
...@@ -234,14 +237,9 @@ struct exynos_drm_g2d_private { ...@@ -234,14 +237,9 @@ struct exynos_drm_g2d_private {
struct list_head userptr_list; struct list_head userptr_list;
}; };
struct exynos_drm_ipp_private {
struct device *dev;
struct list_head event_list;
};
struct drm_exynos_file_private { struct drm_exynos_file_private {
struct exynos_drm_g2d_private *g2d_priv; struct exynos_drm_g2d_private *g2d_priv;
struct exynos_drm_ipp_private *ipp_priv; struct device *ipp_dev;
struct file *anon_filp; struct file *anon_filp;
}; };
......
This diff is collapsed.
...@@ -1887,6 +1887,7 @@ static const struct of_device_id fimc_of_match[] = { ...@@ -1887,6 +1887,7 @@ static const struct of_device_id fimc_of_match[] = {
{ .compatible = "samsung,exynos4212-fimc" }, { .compatible = "samsung,exynos4212-fimc" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, fimc_of_match);
struct platform_driver fimc_driver = { struct platform_driver fimc_driver = {
.probe = fimc_probe, .probe = fimc_probe,
......
This diff is collapsed.
...@@ -1042,8 +1042,23 @@ static int g2d_check_reg_offset(struct device *dev, ...@@ -1042,8 +1042,23 @@ static int g2d_check_reg_offset(struct device *dev,
int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data, int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
struct drm_file *file) struct drm_file *file)
{ {
struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
struct device *dev;
struct g2d_data *g2d;
struct drm_exynos_g2d_get_ver *ver = data; struct drm_exynos_g2d_get_ver *ver = data;
if (!g2d_priv)
return -ENODEV;
dev = g2d_priv->dev;
if (!dev)
return -ENODEV;
g2d = dev_get_drvdata(dev);
if (!g2d)
return -EFAULT;
ver->major = G2D_HW_MAJOR_VER; ver->major = G2D_HW_MAJOR_VER;
ver->minor = G2D_HW_MINOR_VER; ver->minor = G2D_HW_MINOR_VER;
...@@ -1056,7 +1071,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1056,7 +1071,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
{ {
struct drm_exynos_file_private *file_priv = file->driver_priv; struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
struct device *dev = g2d_priv->dev; struct device *dev;
struct g2d_data *g2d; struct g2d_data *g2d;
struct drm_exynos_g2d_set_cmdlist *req = data; struct drm_exynos_g2d_set_cmdlist *req = data;
struct drm_exynos_g2d_cmd *cmd; struct drm_exynos_g2d_cmd *cmd;
...@@ -1067,6 +1082,10 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1067,6 +1082,10 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
int size; int size;
int ret; int ret;
if (!g2d_priv)
return -ENODEV;
dev = g2d_priv->dev;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
...@@ -1223,13 +1242,17 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1223,13 +1242,17 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
{ {
struct drm_exynos_file_private *file_priv = file->driver_priv; struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
struct device *dev = g2d_priv->dev; struct device *dev;
struct g2d_data *g2d; struct g2d_data *g2d;
struct drm_exynos_g2d_exec *req = data; struct drm_exynos_g2d_exec *req = data;
struct g2d_runqueue_node *runqueue_node; struct g2d_runqueue_node *runqueue_node;
struct list_head *run_cmdlist; struct list_head *run_cmdlist;
struct list_head *event_list; struct list_head *event_list;
if (!g2d_priv)
return -ENODEV;
dev = g2d_priv->dev;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
...@@ -1544,8 +1567,10 @@ static const struct dev_pm_ops g2d_pm_ops = { ...@@ -1544,8 +1567,10 @@ static const struct dev_pm_ops g2d_pm_ops = {
static const struct of_device_id exynos_g2d_match[] = { static const struct of_device_id exynos_g2d_match[] = {
{ .compatible = "samsung,exynos5250-g2d" }, { .compatible = "samsung,exynos5250-g2d" },
{ .compatible = "samsung,exynos4212-g2d" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, exynos_g2d_match);
struct platform_driver g2d_driver = { struct platform_driver g2d_driver = {
.probe = g2d_probe, .probe = g2d_probe,
......
...@@ -301,7 +301,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev, ...@@ -301,7 +301,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
unsigned int gem_handle, unsigned int gem_handle,
struct drm_file *filp) struct drm_file *filp)
{ {
struct exynos_drm_gem_obj *exynos_gem_obj;
struct drm_gem_object *obj; struct drm_gem_object *obj;
obj = drm_gem_object_lookup(dev, filp, gem_handle); obj = drm_gem_object_lookup(dev, filp, gem_handle);
...@@ -310,8 +309,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev, ...@@ -310,8 +309,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
return; return;
} }
exynos_gem_obj = to_exynos_gem_obj(obj);
drm_gem_object_unreference_unlocked(obj); drm_gem_object_unreference_unlocked(obj);
/* /*
......
This diff is collapsed.
...@@ -48,7 +48,7 @@ struct drm_exynos_ipp_cmd_work { ...@@ -48,7 +48,7 @@ struct drm_exynos_ipp_cmd_work {
/* /*
* A structure of command node. * A structure of command node.
* *
* @priv: IPP private information. * @dev: IPP device.
* @list: list head to command queue information. * @list: list head to command queue information.
* @event_list: list head of event. * @event_list: list head of event.
* @mem_list: list head to source,destination memory queue information. * @mem_list: list head to source,destination memory queue information.
...@@ -64,7 +64,7 @@ struct drm_exynos_ipp_cmd_work { ...@@ -64,7 +64,7 @@ struct drm_exynos_ipp_cmd_work {
* @state: state of command node. * @state: state of command node.
*/ */
struct drm_exynos_ipp_cmd_node { struct drm_exynos_ipp_cmd_node {
struct exynos_drm_ipp_private *priv; struct device *dev;
struct list_head list; struct list_head list;
struct list_head event_list; struct list_head event_list;
struct list_head mem_list[EXYNOS_DRM_OPS_MAX]; struct list_head mem_list[EXYNOS_DRM_OPS_MAX];
......
...@@ -691,6 +691,7 @@ static const struct of_device_id exynos_rotator_match[] = { ...@@ -691,6 +691,7 @@ static const struct of_device_id exynos_rotator_match[] = {
}, },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, exynos_rotator_match);
static int rotator_probe(struct platform_device *pdev) static int rotator_probe(struct platform_device *pdev)
{ {
......
...@@ -84,6 +84,7 @@ struct hdmi_resources { ...@@ -84,6 +84,7 @@ struct hdmi_resources {
struct clk *sclk_hdmiphy; struct clk *sclk_hdmiphy;
struct clk *mout_hdmi; struct clk *mout_hdmi;
struct regulator_bulk_data *regul_bulk; struct regulator_bulk_data *regul_bulk;
struct regulator *reg_hdmi_en;
int regul_count; int regul_count;
}; };
...@@ -592,6 +593,13 @@ static struct hdmi_driver_data exynos4212_hdmi_driver_data = { ...@@ -592,6 +593,13 @@ static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
.is_apb_phy = 0, .is_apb_phy = 0,
}; };
static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
.type = HDMI_TYPE13,
.phy_confs = hdmiphy_v13_configs,
.phy_conf_count = ARRAY_SIZE(hdmiphy_v13_configs),
.is_apb_phy = 0,
};
static struct hdmi_driver_data exynos5_hdmi_driver_data = { static struct hdmi_driver_data exynos5_hdmi_driver_data = {
.type = HDMI_TYPE14, .type = HDMI_TYPE14,
.phy_confs = hdmiphy_v13_configs, .phy_confs = hdmiphy_v13_configs,
...@@ -1241,14 +1249,13 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr) ...@@ -1241,14 +1249,13 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
static void hdmi_audio_init(struct hdmi_context *hdata) static void hdmi_audio_init(struct hdmi_context *hdata)
{ {
u32 sample_rate, bits_per_sample, frame_size_code; u32 sample_rate, bits_per_sample;
u32 data_num, bit_ch, sample_frq; u32 data_num, bit_ch, sample_frq;
u32 val; u32 val;
u8 acr[7]; u8 acr[7];
sample_rate = 44100; sample_rate = 44100;
bits_per_sample = 16; bits_per_sample = 16;
frame_size_code = 0;
switch (bits_per_sample) { switch (bits_per_sample) {
case 20: case 20:
...@@ -2168,7 +2175,6 @@ static int hdmi_resources_init(struct hdmi_context *hdata) ...@@ -2168,7 +2175,6 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
struct device *dev = hdata->dev; struct device *dev = hdata->dev;
struct hdmi_resources *res = &hdata->res; struct hdmi_resources *res = &hdata->res;
static char *supply[] = { static char *supply[] = {
"hdmi-en",
"vdd", "vdd",
"vdd_osc", "vdd_osc",
"vdd_pll", "vdd_pll",
...@@ -2228,6 +2234,20 @@ static int hdmi_resources_init(struct hdmi_context *hdata) ...@@ -2228,6 +2234,20 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
} }
res->regul_count = ARRAY_SIZE(supply); res->regul_count = ARRAY_SIZE(supply);
res->reg_hdmi_en = devm_regulator_get(dev, "hdmi-en");
if (IS_ERR(res->reg_hdmi_en) && PTR_ERR(res->reg_hdmi_en) != -ENOENT) {
DRM_ERROR("failed to get hdmi-en regulator\n");
return PTR_ERR(res->reg_hdmi_en);
}
if (!IS_ERR(res->reg_hdmi_en)) {
ret = regulator_enable(res->reg_hdmi_en);
if (ret) {
DRM_ERROR("failed to enable hdmi-en regulator\n");
return ret;
}
} else
res->reg_hdmi_en = NULL;
return ret; return ret;
fail: fail:
DRM_ERROR("HDMI resource init - failed\n"); DRM_ERROR("HDMI resource init - failed\n");
...@@ -2262,6 +2282,9 @@ static struct of_device_id hdmi_match_types[] = { ...@@ -2262,6 +2282,9 @@ static struct of_device_id hdmi_match_types[] = {
{ {
.compatible = "samsung,exynos5-hdmi", .compatible = "samsung,exynos5-hdmi",
.data = &exynos5_hdmi_driver_data, .data = &exynos5_hdmi_driver_data,
}, {
.compatible = "samsung,exynos4210-hdmi",
.data = &exynos4210_hdmi_driver_data,
}, { }, {
.compatible = "samsung,exynos4212-hdmi", .compatible = "samsung,exynos4212-hdmi",
.data = &exynos4212_hdmi_driver_data, .data = &exynos4212_hdmi_driver_data,
...@@ -2272,6 +2295,7 @@ static struct of_device_id hdmi_match_types[] = { ...@@ -2272,6 +2295,7 @@ static struct of_device_id hdmi_match_types[] = {
/* end node */ /* end node */
} }
}; };
MODULE_DEVICE_TABLE (of, hdmi_match_types);
static int hdmi_bind(struct device *dev, struct device *master, void *data) static int hdmi_bind(struct device *dev, struct device *master, void *data)
{ {
...@@ -2494,7 +2518,11 @@ static int hdmi_remove(struct platform_device *pdev) ...@@ -2494,7 +2518,11 @@ static int hdmi_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&hdata->hotplug_work); cancel_delayed_work_sync(&hdata->hotplug_work);
put_device(&hdata->hdmiphy_port->dev); if (hdata->res.reg_hdmi_en)
regulator_disable(hdata->res.reg_hdmi_en);
if (hdata->hdmiphy_port)
put_device(&hdata->hdmiphy_port->dev);
put_device(&hdata->ddc_adpt->dev); put_device(&hdata->ddc_adpt->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
......
...@@ -76,7 +76,7 @@ struct mixer_resources { ...@@ -76,7 +76,7 @@ struct mixer_resources {
struct clk *vp; struct clk *vp;
struct clk *sclk_mixer; struct clk *sclk_mixer;
struct clk *sclk_hdmi; struct clk *sclk_hdmi;
struct clk *sclk_dac; struct clk *mout_mixer;
}; };
enum mixer_version_id { enum mixer_version_id {
...@@ -93,6 +93,7 @@ struct mixer_context { ...@@ -93,6 +93,7 @@ struct mixer_context {
bool interlace; bool interlace;
bool powered; bool powered;
bool vp_enabled; bool vp_enabled;
bool has_sclk;
u32 int_en; u32 int_en;
struct mutex mixer_mutex; struct mutex mixer_mutex;
...@@ -106,6 +107,7 @@ struct mixer_context { ...@@ -106,6 +107,7 @@ struct mixer_context {
struct mixer_drv_data { struct mixer_drv_data {
enum mixer_version_id version; enum mixer_version_id version;
bool is_vp_enabled; bool is_vp_enabled;
bool has_sclk;
}; };
static const u8 filter_y_horiz_tap8[] = { 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,6 +365,11 @@ static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
mixer_reg_writemask(res, MXR_CFG, val, mixer_reg_writemask(res, MXR_CFG, val,
MXR_CFG_VP_ENABLE); MXR_CFG_VP_ENABLE);
/* control blending of graphic layer 0 */
mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
MXR_GRP_CFG_BLEND_PRE_MUL |
MXR_GRP_CFG_PIXEL_BLEND_EN);
} }
break; break;
} }
...@@ -809,19 +816,23 @@ static int vp_resources_init(struct mixer_context *mixer_ctx) ...@@ -809,19 +816,23 @@ static int vp_resources_init(struct mixer_context *mixer_ctx)
dev_err(dev, "failed to get clock 'vp'\n"); dev_err(dev, "failed to get clock 'vp'\n");
return -ENODEV; return -ENODEV;
} }
mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
if (IS_ERR(mixer_res->sclk_mixer)) {
dev_err(dev, "failed to get clock 'sclk_mixer'\n");
return -ENODEV;
}
mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
if (IS_ERR(mixer_res->sclk_dac)) {
dev_err(dev, "failed to get clock 'sclk_dac'\n");
return -ENODEV;
}
if (mixer_res->sclk_hdmi) if (mixer_ctx->has_sclk) {
clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
if (IS_ERR(mixer_res->sclk_mixer)) {
dev_err(dev, "failed to get clock 'sclk_mixer'\n");
return -ENODEV;
}
mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
if (IS_ERR(mixer_res->mout_mixer)) {
dev_err(dev, "failed to get clock 'mout_mixer'\n");
return -ENODEV;
}
if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
clk_set_parent(mixer_res->mout_mixer,
mixer_res->sclk_hdmi);
}
res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
if (res == NULL) { if (res == NULL) {
...@@ -1082,7 +1093,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) ...@@ -1082,7 +1093,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
clk_prepare_enable(res->mixer); clk_prepare_enable(res->mixer);
if (ctx->vp_enabled) { if (ctx->vp_enabled) {
clk_prepare_enable(res->vp); clk_prepare_enable(res->vp);
clk_prepare_enable(res->sclk_mixer); if (ctx->has_sclk)
clk_prepare_enable(res->sclk_mixer);
} }
mutex_lock(&ctx->mixer_mutex); mutex_lock(&ctx->mixer_mutex);
...@@ -1121,7 +1133,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) ...@@ -1121,7 +1133,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
clk_disable_unprepare(res->mixer); clk_disable_unprepare(res->mixer);
if (ctx->vp_enabled) { if (ctx->vp_enabled) {
clk_disable_unprepare(res->vp); clk_disable_unprepare(res->vp);
clk_disable_unprepare(res->sclk_mixer); if (ctx->has_sclk)
clk_disable_unprepare(res->sclk_mixer);
} }
pm_runtime_put_sync(ctx->dev); pm_runtime_put_sync(ctx->dev);
...@@ -1189,9 +1202,15 @@ static struct mixer_drv_data exynos5250_mxr_drv_data = { ...@@ -1189,9 +1202,15 @@ static struct mixer_drv_data exynos5250_mxr_drv_data = {
.is_vp_enabled = 0, .is_vp_enabled = 0,
}; };
static struct mixer_drv_data exynos4212_mxr_drv_data = {
.version = MXR_VER_0_0_0_16,
.is_vp_enabled = 1,
};
static struct mixer_drv_data exynos4210_mxr_drv_data = { static struct mixer_drv_data exynos4210_mxr_drv_data = {
.version = MXR_VER_0_0_0_16, .version = MXR_VER_0_0_0_16,
.is_vp_enabled = 1, .is_vp_enabled = 1,
.has_sclk = 1,
}; };
static struct platform_device_id mixer_driver_types[] = { static struct platform_device_id mixer_driver_types[] = {
...@@ -1208,6 +1227,12 @@ static struct platform_device_id mixer_driver_types[] = { ...@@ -1208,6 +1227,12 @@ static struct platform_device_id mixer_driver_types[] = {
static struct of_device_id mixer_match_types[] = { static struct of_device_id mixer_match_types[] = {
{ {
.compatible = "samsung,exynos4210-mixer",
.data = &exynos4210_mxr_drv_data,
}, {
.compatible = "samsung,exynos4212-mixer",
.data = &exynos4212_mxr_drv_data,
}, {
.compatible = "samsung,exynos5-mixer", .compatible = "samsung,exynos5-mixer",
.data = &exynos5250_mxr_drv_data, .data = &exynos5250_mxr_drv_data,
}, { }, {
...@@ -1220,6 +1245,7 @@ static struct of_device_id mixer_match_types[] = { ...@@ -1220,6 +1245,7 @@ static struct of_device_id mixer_match_types[] = {
/* end node */ /* end node */
} }
}; };
MODULE_DEVICE_TABLE(of, mixer_match_types);
static int mixer_bind(struct device *dev, struct device *manager, void *data) static int mixer_bind(struct device *dev, struct device *manager, void *data)
{ {
...@@ -1251,6 +1277,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) ...@@ -1251,6 +1277,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
ctx->pdev = pdev; ctx->pdev = pdev;
ctx->dev = dev; ctx->dev = dev;
ctx->vp_enabled = drv->is_vp_enabled; ctx->vp_enabled = drv->is_vp_enabled;
ctx->has_sclk = drv->has_sclk;
ctx->mxr_ver = drv->version; ctx->mxr_ver = drv->version;
init_waitqueue_head(&ctx->wait_vsync_queue); init_waitqueue_head(&ctx->wait_vsync_queue);
atomic_set(&ctx->wait_vsync_event, 0); atomic_set(&ctx->wait_vsync_event, 0);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
/* VIDCON0 */ /* VIDCON0 */
#define VIDCON0 0x00 #define VIDCON0 0x00
#define VIDCON0_DSI_EN (1 << 30)
#define VIDCON0_INTERLACE (1 << 29) #define VIDCON0_INTERLACE (1 << 29)
#define VIDCON0_VIDOUT_MASK (0x7 << 26) #define VIDCON0_VIDOUT_MASK (0x7 << 26)
#define VIDCON0_VIDOUT_SHIFT 26 #define VIDCON0_VIDOUT_SHIFT 26
...@@ -355,7 +356,7 @@ ...@@ -355,7 +356,7 @@
#define VIDINTCON0_INT_ENABLE (1 << 0) #define VIDINTCON0_INT_ENABLE (1 << 0)
#define VIDINTCON1 0x134 #define VIDINTCON1 0x134
#define VIDINTCON1_INT_I180 (1 << 2) #define VIDINTCON1_INT_I80 (1 << 2)
#define VIDINTCON1_INT_FRAME (1 << 1) #define VIDINTCON1_INT_FRAME (1 << 1)
#define VIDINTCON1_INT_FIFO (1 << 0) #define VIDINTCON1_INT_FIFO (1 << 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment