aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPer Persson <per.xb.persson@stericsson.com>2011-04-26 16:14:14 +0200
committerJonas ABERG <jonas.aberg@stericsson.com>2011-04-27 16:28:17 +0200
commit6044b9da5b3702c9f236def93210db4e8894d5eb (patch)
treec2783b9367eb9a1231e50751c429afb53f091ed1 /drivers
parent5473eb520328523576d47c896a0010a781ec280f (diff)
video: mcde_hdmi: Support for HDMI user space service
Add changes needed by HDMI service in user space. HDMI service is a user space service that provide functionality for applications using HDMI. ST-Ericsson ID: 335747 ST-Ericsson Linux next: Not tested, ER 282779 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I7c2ffd5ae61310f9a152ca984c4f62152fc1e2e0 Signed-off-by: Per Persson <per.xb.persson@stericsson.com> Change-Id: Ie04b52ce91b33961ed36201e1019d92fb696487e Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/20950 Reviewed-by: Marcel TUNNISSEN <marcel.tuennissen@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/dispdev/dispdev.c30
-rw-r--r--drivers/video/av8100/av8100.c21
-rw-r--r--drivers/video/av8100/hdmi.c84
-rw-r--r--drivers/video/mcde/Kconfig9
-rw-r--r--drivers/video/mcde/display-av8100.c309
-rw-r--r--drivers/video/mcde/mcde_fb.c24
6 files changed, 454 insertions, 23 deletions
diff --git a/drivers/misc/dispdev/dispdev.c b/drivers/misc/dispdev/dispdev.c
index dc6266d241b..af854841d95 100644
--- a/drivers/misc/dispdev/dispdev.c
+++ b/drivers/misc/dispdev/dispdev.c
@@ -162,9 +162,8 @@ static void get_ovly_info(struct dispdev_config *cfg,
static int dispdev_set_config(struct dispdev *dd, struct dispdev_config *cfg)
{
- int ret, i;
+ int ret;
struct mcde_overlay_info info;
- u8 reuse_buffers = false;
if (memcmp(&dd->config, cfg, sizeof(struct dispdev_config)) == 0)
return 0;
@@ -455,7 +454,30 @@ out:
return ret;
}
-static void dispdev_destroy(void)
+void dispdev_destroy(struct mcde_display_device *ddev)
+{
+ struct dispdev *dd;
+ struct dispdev *tmp;
+
+ mutex_lock(&dev_list_lock);
+ list_for_each_entry_safe(dd, tmp, &dev_list, list) {
+ if (dd->ddev == ddev) {
+ list_del(&dd->list);
+ misc_deregister(&dd->mdev);
+ mcde_dss_destroy_overlay(dd->ovly);
+ /*
+ * TODO: Uncomment when DSS has reference
+ * counting of enable/disable
+ */
+ /* mcde_dss_disable_display(dd->ddev); */
+ kfree(dd);
+ break;
+ }
+ }
+ mutex_unlock(&dev_list_lock);
+}
+
+static void dispdev_destroy_all(void)
{
struct dispdev *dd;
struct dispdev *tmp;
@@ -489,7 +511,7 @@ module_init(dispdev_init);
static void __exit dispdev_exit(void)
{
- dispdev_destroy();
+ dispdev_destroy_all();
pr_info("%s\n", __func__);
}
module_exit(dispdev_exit);
diff --git a/drivers/video/av8100/av8100.c b/drivers/video/av8100/av8100.c
index 29c553d0522..b2920f277ac 100644
--- a/drivers/video/av8100/av8100.c
+++ b/drivers/video/av8100/av8100.c
@@ -1059,10 +1059,7 @@ static void av8100_set_state(enum av8100_operating_mode state)
{
g_av8100_status.av8100_state = state;
- if (state == AV8100_OPMODE_UNDEFINED)
- g_av8100_status.hdmi_on = false;
-
- if (state == AV8100_OPMODE_STANDBY) {
+ if (state <= AV8100_OPMODE_STANDBY) {
clr_plug_status(AV8100_HDMI_PLUGIN);
clr_plug_status(AV8100_CVBS_PLUGIN);
g_av8100_status.hdmi_on = false;
@@ -1929,15 +1926,23 @@ static int av8100_powerup2(void)
int av8100_powerup(void)
{
+ int ret = 0;
+
if (av8100_status_get().av8100_state == AV8100_OPMODE_UNDEFINED)
return -EINVAL;
- if (av8100_powerup1()) {
- dev_err(av8100dev, "av8100_powerup1 fail\n");
- return -EFAULT;
+ if (av8100_status_get().av8100_state < AV8100_OPMODE_STANDBY) {
+ ret = av8100_powerup1();
+ if (ret) {
+ dev_err(av8100dev, "av8100_powerup1 fail\n");
+ return -EFAULT;
+ }
}
- return av8100_powerup2();
+ if (av8100_status_get().av8100_state < AV8100_OPMODE_SCAN)
+ ret = av8100_powerup2();
+
+ return ret;
}
EXPORT_SYMBOL(av8100_powerup);
diff --git a/drivers/video/av8100/hdmi.c b/drivers/video/av8100/hdmi.c
index 3459bac69fd..be267188018 100644
--- a/drivers/video/av8100/hdmi.c
+++ b/drivers/video/av8100/hdmi.c
@@ -82,6 +82,10 @@ static ssize_t show_plugstatus(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t store_poweronoff(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_poweronoff(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_evwakeup(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
static DEVICE_ATTR(storeastext, S_IWUSR, NULL, store_storeastext);
static DEVICE_ATTR(plugdeten, S_IWUSR, NULL, store_plugdeten);
@@ -103,7 +107,9 @@ static DEVICE_ATTR(evread, S_IRUGO, show_evread, NULL);
static DEVICE_ATTR(evclr, S_IWUSR, NULL, store_evclr);
static DEVICE_ATTR(audiocfg, S_IWUSR, NULL, store_audiocfg);
static DEVICE_ATTR(plugstatus, S_IRUGO, show_plugstatus, NULL);
-static DEVICE_ATTR(poweronoff, S_IWUSR, NULL, store_poweronoff);
+static DEVICE_ATTR(poweronoff, S_IRUGO | S_IWUSR, show_poweronoff,
+ store_poweronoff);
+static DEVICE_ATTR(evwakeup, S_IWUSR, NULL, store_evwakeup);
/* Hex to int conversion */
static unsigned int htoi(const char *ptr)
@@ -608,6 +614,24 @@ static int events_clear(u8 ev)
return 0;
}
+static int event_wakeup(void)
+{
+ struct kobject *kobj = &hdmidev->kobj;
+
+ dev_dbg(hdmidev, "%s", __func__);
+
+ LOCK_HDMI_EVENTS;
+ events |= HDMI_EVENT_WAKEUP;
+ events_received = true;
+ UNLOCK_HDMI_EVENTS;
+
+ /* Wake up application waiting for event via call to poll() */
+ sysfs_notify(kobj, NULL, SYSFS_EVENT_FILENAME);
+ wake_up_interruptible(&hdmi_event_wq);
+
+ return 0;
+}
+
static int audiocfg(struct audio_cfg *cfg)
{
union av8100_configuration config;
@@ -1614,6 +1638,44 @@ static ssize_t store_poweronoff(struct device *dev,
return count;
}
+static ssize_t show_poweronoff(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_driver_data *hdmi_driver_data;
+ int index = 0;
+ struct av8100_status status;
+ u8 power_state;
+
+ dev_dbg(hdmidev, "%s\n", __func__);
+
+ hdmi_driver_data = dev_get_drvdata(dev);
+
+ status = av8100_status_get();
+ if (status.av8100_state < AV8100_OPMODE_SCAN)
+ power_state = 0;
+ else
+ power_state = 1;
+
+ if (hdmi_driver_data->store_as_hextext) {
+ snprintf(buf + index, 3, "%02x", power_state);
+ index += 3;
+ } else {
+ *(buf + index++) = power_state;
+ }
+
+ return index;
+}
+
+static ssize_t store_evwakeup(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ dev_dbg(hdmidev, "%s\n", __func__);
+
+ event_wakeup();
+
+ return count;
+}
+
static int hdmi_open(struct inode *inode, struct file *filp)
{
if (device_open)
@@ -1915,6 +1977,21 @@ ioc_hdcploadaes_err:
}
break;
+ case IOC_EVENT_WAKEUP:
+ /* Trigger event */
+ event_wakeup();
+ break;
+
+ case IOC_POWERSTATE:
+ status = av8100_status_get();
+ value = status.av8100_state >= AV8100_OPMODE_SCAN;
+
+ if (copy_to_user((void *)arg, (void *)&value,
+ sizeof(u8))) {
+ return -EINVAL;
+ }
+ break;
+
/* Internal */
case IOC_HDMI_ENABLE_INTERRUPTS:
av8100_disable_interrupt();
@@ -2074,10 +2151,12 @@ void hdmi_event(enum av8100_hdmi_event ev)
/* Set event */
switch (ev) {
case AV8100_HDMI_EVENT_HDMI_PLUGIN:
+ events &= ~HDMI_EVENT_HDMI_PLUGOUT;
events |= events_mask & HDMI_EVENT_HDMI_PLUGIN;
break;
case AV8100_HDMI_EVENT_HDMI_PLUGOUT:
+ events &= ~HDMI_EVENT_HDMI_PLUGIN;
events |= events_mask & HDMI_EVENT_HDMI_PLUGOUT;
break;
@@ -2177,6 +2256,8 @@ int __init hdmi_init(void)
dev_info(hdmidev, "Unable to create plugstatus attribute\n");
if (device_create_file(hdmidev, &dev_attr_poweronoff))
dev_info(hdmidev, "Unable to create poweronoff attribute\n");
+ if (device_create_file(hdmidev, &dev_attr_evwakeup))
+ dev_info(hdmidev, "Unable to create evwakeup attribute\n");
/* Register event callback */
av8100_hdmi_event_cb_set(hdmi_event);
@@ -2211,6 +2292,7 @@ void hdmi_exit(void)
device_remove_file(hdmidev, &dev_attr_audiocfg);
device_remove_file(hdmidev, &dev_attr_plugstatus);
device_remove_file(hdmidev, &dev_attr_poweronoff);
+ device_remove_file(hdmidev, &dev_attr_evwakeup);
hdmi_driver_data = dev_get_drvdata(hdmidev);
kfree(hdmi_driver_data);
diff --git a/drivers/video/mcde/Kconfig b/drivers/video/mcde/Kconfig
index c97387a97ed..a1310332cf9 100644
--- a/drivers/video/mcde/Kconfig
+++ b/drivers/video/mcde/Kconfig
@@ -44,6 +44,15 @@ config MCDE_DISPLAY_AV8100
depends on FB_MCDE
select AV8100
+config MCDE_DISPLAY_HDMI_FB_AUTO_CREATE
+ bool "HDMI_FB_AUTO_CREATE"
+ default y
+ depends on MCDE_DISPLAY_AV8100
+ ---help---
+ Say Y if you want the HDMI frame buffer to be created on start
+ Say N if you want the HDMI frame buffer to be created when HDMI
+ cable is plugged (needs user space HDMIservice)
+
config MCDE_DISPLAY_AB8500_DENC
tristate "AB8500 CVBS display driver"
depends on FB_MCDE
diff --git a/drivers/video/mcde/display-av8100.c b/drivers/video/mcde/display-av8100.c
index 84818a558fc..5d400a9958e 100644
--- a/drivers/video/mcde/display-av8100.c
+++ b/drivers/video/mcde/display-av8100.c
@@ -24,10 +24,10 @@
#define SWITCH_HELPSTR ", 0=HDMI, 1=SDTV, 2=DVI\n"
-struct display_driver_data {
- struct regulator *cvbs_regulator;
- bool cvbs_regulator_enabled;
- bool update_port_pixel_format;
+struct cea_vesa_video_mode {
+ u32 cea;
+ u32 vesa_cea_nr;
+ struct mcde_video_mode *video_mode;
};
static int hdmi_try_video_mode(
@@ -36,6 +36,8 @@ static int hdmi_set_video_mode(
struct mcde_display_device *ddev, struct mcde_video_mode *video_mode);
static int hdmi_set_pixel_format(
struct mcde_display_device *ddev, enum mcde_ovly_pix_fmt format);
+static struct mcde_video_mode *video_mode_get(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr);
static ssize_t show_hdmisdtvswitch(struct device *dev,
struct device_attribute *attr, char *buf);
@@ -45,6 +47,23 @@ static ssize_t show_input_pixel_format(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t store_input_pixel_format(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_disponoff(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_disponoff(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t show_vesacea(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t show_timing(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_timing(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t store_stayalive(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(disponoff, S_IRUGO | S_IWUSR, show_disponoff,
+ store_disponoff);
+static DEVICE_ATTR(vesacea, S_IRUGO, show_vesacea, NULL);
+static DEVICE_ATTR(timing, S_IRUGO | S_IWUSR, show_timing, store_timing);
+static DEVICE_ATTR(stayalive, S_IWUSR, NULL, store_stayalive);
static DEVICE_ATTR(hdmisdtvswitch, S_IRUGO | S_IWUSR, show_hdmisdtvswitch,
store_hdmisdtvswitch);
@@ -137,6 +156,134 @@ static ssize_t store_input_pixel_format(struct device *dev,
return count;
}
+static ssize_t show_disponoff(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (ddev->fbi && driver_data->fbdevname) {
+ dev_dbg(dev, "name:%s\n", driver_data->fbdevname);
+ strcpy(buf, driver_data->fbdevname);
+ return strlen(driver_data->fbdevname) + 1;
+ }
+ return 0;
+}
+
+static ssize_t store_disponoff(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *mdev = to_mcde_display_device(dev);
+ bool enable = false;
+ u8 cea = 0;
+ u8 vesa_cea_nr = 0;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if ((count != DISPONOFF_SIZE) && (count != DISPONOFF_SIZE + 1))
+ return -EINVAL;
+
+ if ((*buf == '0') && (*(buf + 1) == '1'))
+ enable = true;
+ cea = (hex_to_bin(buf[2]) << 4) + hex_to_bin(buf[3]);
+ vesa_cea_nr = (hex_to_bin(buf[4]) << 4) + hex_to_bin(buf[5]);
+ dev_dbg(dev, "enable:%d cea:%d nr:%d\n", enable, cea, vesa_cea_nr);
+
+ hdmi_fb_onoff(mdev, enable, cea, vesa_cea_nr);
+
+ return count;
+}
+
+static ssize_t show_timing(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+ struct mcde_video_mode *video_mode;
+ int index;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ index = 0;
+ if (driver_data->video_mode) {
+ video_mode = driver_data->video_mode;
+ memcpy(buf + index, &video_mode->xres, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->yres, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->pixclock, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->hbp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->hfp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->vbp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->vfp, sizeof(u32));
+ index += sizeof(u32);
+ memcpy(buf + index, &video_mode->interlaced, sizeof(u32));
+ index += sizeof(u32);
+ }
+ return index;
+}
+
+static ssize_t store_timing(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (count != TIMING_SIZE)
+ return -EINVAL;
+
+ driver_data->video_mode = video_mode_get(ddev, *buf, *(buf + 1));
+
+ return count;
+}
+
+static ssize_t store_stayalive(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mcde_display_device *ddev = to_mcde_display_device(dev);
+
+ if (count != STAYALIVE_SIZE)
+ return -EINVAL;
+
+ if ((*buf == 1) || (*buf == '1'))
+ ddev->stay_alive = true;
+ else
+ ddev->stay_alive = false;
+
+ dev_dbg(dev, "%s %d\n", __func__, ddev->stay_alive);
+
+ return count;
+}
+
+static int ceanr_convert(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr, int buffering,
+ u16 *w, u16 *h, u16 *vw, u16 *vh)
+{
+ struct mcde_video_mode *video_mode;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ video_mode = video_mode_get(ddev, cea, vesa_cea_nr);
+ if (video_mode) {
+ *w = video_mode->xres;
+ *h = video_mode->yres;
+ *vw = video_mode->xres;
+ *vh = video_mode->yres * buffering;
+ dev_dbg(&ddev->dev, "cea:%d nr:%d found\n",
+ cea, vesa_cea_nr);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
/* Supported HDMI modes */
static struct mcde_video_mode video_modes_supp_hdmi[] = {
/* 640_480_60_P */
@@ -249,6 +396,124 @@ static struct mcde_video_mode video_modes_supp_sdtv[] = {
},
};
+static struct cea_vesa_video_mode cea_vesa_video_mode[] = {
+ /* 640_480_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 1,
+ .video_mode = &video_modes_supp_hdmi[0],
+ },
+ /* 720_480_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 2,
+ .video_mode = &video_modes_supp_hdmi[1],
+ },
+ /* 720_480_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 3,
+ .video_mode = &video_modes_supp_hdmi[1],
+ },
+ /* 720_576_50_P */
+ {
+ .cea = 1, .vesa_cea_nr = 17,
+ .video_mode = &video_modes_supp_hdmi[2],
+ },
+ /* 720_576_50_P */
+ {
+ .cea = 1, .vesa_cea_nr = 18,
+ .video_mode = &video_modes_supp_hdmi[2],
+ },
+ /* 1280_720_60_P */
+ {
+ .cea = 1, .vesa_cea_nr = 4,
+ .video_mode = &video_modes_supp_hdmi[3],
+ },
+ /* 1280_720_50_P */
+ {
+ .cea = 1, .vesa_cea_nr = 19,
+ .video_mode = &video_modes_supp_hdmi[4],
+ },
+ /* 1920_1080_30_P */
+ {
+ .cea = 1, .vesa_cea_nr = 34,
+ .video_mode = &video_modes_supp_hdmi[5],
+ },
+ /* 1920_1080_24_P */
+ {
+ .cea = 1, .vesa_cea_nr = 32,
+ .video_mode = &video_modes_supp_hdmi[6],
+ },
+ /* 1920_1080_25_P */
+ {
+ .cea = 1, .vesa_cea_nr = 33,
+ .video_mode = &video_modes_supp_hdmi[7],
+ },
+ /* 720_480_60_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 6,
+ .video_mode = &video_modes_supp_hdmi[8],
+ },
+ /* 720_480_60_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 7,
+ .video_mode = &video_modes_supp_hdmi[8],
+ },
+ /* 720_576_50_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 21,
+ .video_mode = &video_modes_supp_hdmi[9],
+ },
+ /* 720_576_50_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 22,
+ .video_mode = &video_modes_supp_hdmi[9],
+ },
+ /* 1920_1080_50_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 20,
+ .video_mode = &video_modes_supp_hdmi[10],
+ },
+ /* 1920_1080_60_I) */
+ {
+ .cea = 1, .vesa_cea_nr = 5,
+ .video_mode = &video_modes_supp_hdmi[11],
+ },
+};
+
+static ssize_t show_vesacea(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int findex;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ for (findex = 0; findex < ARRAY_SIZE(cea_vesa_video_mode); findex++) {
+ *(buf + findex * 2) = cea_vesa_video_mode[findex].cea;
+ *(buf + findex * 2 + 1) =
+ cea_vesa_video_mode[findex].vesa_cea_nr;
+ }
+ *(buf + findex * 2) = '\0';
+
+ return findex * 2 + 1;
+}
+
+static struct mcde_video_mode *video_mode_get(struct mcde_display_device *ddev,
+ u8 cea, u8 vesa_cea_nr)
+{
+ int findex;
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+
+ for (findex = 0; findex < ARRAY_SIZE(cea_vesa_video_mode); findex++)
+ if ((cea == cea_vesa_video_mode[findex].cea) &&
+ (vesa_cea_nr ==
+ cea_vesa_video_mode[findex].vesa_cea_nr)) {
+ dev_dbg(&ddev->dev, "cea:%d nr:%d\n", cea, vesa_cea_nr);
+ return cea_vesa_video_mode[findex].video_mode;
+ }
+
+ return NULL;
+}
+
#define AV8100_MAX_LEVEL 255
static int hdmi_try_video_mode(
@@ -445,17 +710,20 @@ static int hdmi_set_video_mode(
dev_err(&dev->dev, "av8100_powerup failed\n");
return ret;
}
+ }
+ if (status.av8100_state < AV8100_OPMODE_IDLE) {
ret = av8100_download_firmware(NULL, 0, I2C_INTERFACE);
if (ret) {
dev_err(&dev->dev, "av8100_download_firmware failed\n");
av8100_powerdown();
return ret;
}
- } else if (av8100_disable_interrupt()) {
- return -EFAULT;
}
+ if (av8100_disable_interrupt())
+ return -EFAULT;
+
/*
* Don't look at dev->port->hdmi_sdtv_switch; it states only which
* one should be started, not which one is currently working
@@ -817,6 +1085,14 @@ static int hdmi_set_power_mode(struct mcde_display_device *ddev,
if (ret)
return ret;
}
+
+ ret = av8100_powerup();
+ if (ret) {
+ dev_err(&ddev->dev, "av8100_powerup failed\n");
+ return ret;
+ }
+ av8100_enable_interrupt();
+
/*
* the regulator for analog TV out is only enabled here,
* this means that one needs to switch to the OFF state
@@ -907,14 +1183,27 @@ static int __devinit hdmi_probe(struct mcde_display_device *dev)
dev->apply_config = hdmi_apply_config;
dev->set_pixel_format = hdmi_set_pixel_format;
dev->set_power_mode = hdmi_set_power_mode;
+ dev->ceanr_convert = ceanr_convert;
- /* Create sysfs file for switching between hdmi and sdtv */
+ /* Create sysfs files */
if (device_create_file(&dev->dev, &dev_attr_hdmisdtvswitch))
dev_info(&dev->dev,
"Unable to create hdmisdtvswitch attr\n");
if (device_create_file(&dev->dev, &dev_attr_input_pixel_format))
dev_info(&dev->dev,
"Unable to create input_pixel_format attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_disponoff))
+ dev_info(&dev->dev,
+ "Unable to create disponoff attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_vesacea))
+ dev_info(&dev->dev,
+ "Unable to create ceavesa attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_timing))
+ dev_info(&dev->dev,
+ "Unable to create timing attr\n");
+ if (device_create_file(&dev->dev, &dev_attr_stayalive))
+ dev_info(&dev->dev,
+ "Unable to create stayalive attr\n");
if (pdata->cvbs_regulator_id) {
driver_data->cvbs_regulator = regulator_get(&dev->dev,
@@ -944,9 +1233,13 @@ static int __devexit hdmi_remove(struct mcde_display_device *dev)
struct mcde_display_hdmi_platform_data *pdata =
dev->dev.platform_data;
- /* Remove sysfs file */
+ /* Remove sysfs files */
device_remove_file(&dev->dev, &dev_attr_input_pixel_format);
device_remove_file(&dev->dev, &dev_attr_hdmisdtvswitch);
+ device_remove_file(&dev->dev, &dev_attr_disponoff);
+ device_remove_file(&dev->dev, &dev_attr_vesacea);
+ device_remove_file(&dev->dev, &dev_attr_timing);
+ device_remove_file(&dev->dev, &dev_attr_stayalive);
dev->set_power_mode(dev, MCDE_DISPLAY_PM_OFF);
diff --git a/drivers/video/mcde/mcde_fb.c b/drivers/video/mcde/mcde_fb.c
index 8b1cca47339..49924e4fe5d 100644
--- a/drivers/video/mcde/mcde_fb.c
+++ b/drivers/video/mcde/mcde_fb.c
@@ -209,6 +209,7 @@ static int init_var_fmt(struct fb_var_screeninfo *var,
var->yoffset = 0;
var->activate = FB_ACTIVATE_NOW;
var->rotate = rotate;
+
return 0;
};
@@ -692,6 +693,8 @@ struct fb_info *mcde_fb_create(struct mcde_display_device *ddev,
if (ret)
goto fb_register_failed;
+ ddev->fbi = fbi;
+
#ifdef CONFIG_HAS_EARLYSUSPEND
mfb->early_suspend.level =
EARLY_SUSPEND_LEVEL_DISABLE_FB;
@@ -726,9 +729,26 @@ int mcde_fb_attach_overlay(struct fb_info *fb_info, struct mcde_overlay *ovl)
return -EINVAL;
}
-void mcde_fb_destroy(struct fb_info *fb_info)
+void mcde_fb_destroy(struct mcde_display_device *dev)
{
- /* TODO: clean up */
+ struct mcde_fb *mfb;
+ int i;
+
+ dev_vdbg(&dev->dev, "%s\n", __func__);
+
+ mcde_dss_disable_display(dev);
+ mcde_dss_close_channel(dev);
+
+ mfb = to_mcde_fb(dev->fbi);
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ if (mfb->ovlys[i])
+ mcde_dss_destroy_overlay(mfb->ovlys[i]);
+ }
+
+ unregister_framebuffer(dev->fbi);
+ free_fb_mem(dev->fbi);
+ framebuffer_release(dev->fbi);
+ dev->fbi = NULL;
}
/* Overlay fbs' platform device */