diff options
Diffstat (limited to 'drivers/video')
25 files changed, 1179 insertions, 2195 deletions
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 6ddb401552c..609a2807317 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -30,13 +30,6 @@ config PANEL_NEC_NL8048HL11_01B This NEC NL8048HL11-01B panel is TFT LCD used in the Zoom2/3/3630 sdp boards. -config PANEL_PICODLP - tristate "TI PICO DLP mini-projector" - depends on OMAP2_DSS && I2C - help - A mini-projector used in TI's SDP4430 and EVM boards - For more info please visit http://www.dlp.com/projector/ - config PANEL_TAAL tristate "Taal DSI Panel" depends on OMAP2_DSS_DSI diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index d90f73c8716..0f601ab3abf 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile @@ -4,6 +4,5 @@ obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o obj-$(CONFIG_PANEL_TAAL) += panel-taal.o -obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c deleted file mode 100644 index 8d6190c544f..00000000000 --- a/drivers/video/omap2/displays/panel-picodlp.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - * picodlp panel driver - * picodlp_i2c_driver: i2c_client driver - * - * Copyright (C) 2009-2011 Texas Instruments - * Author: Mythri P K <mythripk@ti.com> - * Mayuresh Janorkar <mayur@ti.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/input.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/firmware.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/i2c.h> -#include <linux/delay.h> -#include <linux/gpio.h> - -#include <video/omapdss.h> -#include <video/omap-panel-picodlp.h> - -#include "panel-picodlp.h" - -struct picodlp_data { - struct mutex lock; - struct i2c_client *picodlp_i2c_client; -}; - -static struct i2c_board_info picodlp_i2c_board_info = { - I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b), -}; - -struct picodlp_i2c_data { - struct mutex xfer_lock; -}; - -static struct i2c_device_id picodlp_i2c_id[] = { - { "picodlp_i2c_driver", 0 }, -}; - -struct picodlp_i2c_command { - u8 reg; - u32 value; -}; - -static struct omap_video_timings pico_ls_timings = { - .x_res = 864, - .y_res = 480, - .hsw = 7, - .hfp = 11, - .hbp = 7, - - .pixel_clock = 19200, - - .vsw = 2, - .vfp = 3, - .vbp = 14, -}; - -static inline struct picodlp_panel_data - *get_panel_data(const struct omap_dss_device *dssdev) -{ - return (struct picodlp_panel_data *) dssdev->data; -} - -static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg) -{ - u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4]; - struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); - struct i2c_msg msg[2]; - - mutex_lock(&picodlp_i2c_data->xfer_lock); - - msg[0].addr = client->addr; - msg[0].flags = 0; - msg[0].len = 2; - msg[0].buf = read_cmd; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].len = 4; - msg[1].buf = data; - - i2c_transfer(client->adapter, msg, 2); - mutex_unlock(&picodlp_i2c_data->xfer_lock); - return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24)); -} - -static int picodlp_i2c_write_block(struct i2c_client *client, - u8 *data, int len) -{ - struct i2c_msg msg; - int i, r, msg_count = 1; - - struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); - - if (len < 1 || len > 32) { - dev_err(&client->dev, - "too long syn_write_block len %d\n", len); - return -EIO; - } - mutex_lock(&picodlp_i2c_data->xfer_lock); - - msg.addr = client->addr; - msg.flags = 0; - msg.len = len; - msg.buf = data; - r = i2c_transfer(client->adapter, &msg, msg_count); - mutex_unlock(&picodlp_i2c_data->xfer_lock); - - /* - * i2c_transfer returns: - * number of messages sent in case of success - * a negative error number in case of failure - */ - if (r != msg_count) - goto err; - - /* In case of success */ - for (i = 0; i < len; i++) - dev_dbg(&client->dev, - "addr %x bw 0x%02x[%d]: 0x%02x\n", - client->addr, data[0] + i, i, data[i]); - - return 0; -err: - dev_err(&client->dev, "picodlp_i2c_write error\n"); - return r; -} - -static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value) -{ - u8 data[5]; - int i; - - data[0] = reg; - for (i = 1; i < 5; i++) - data[i] = (value >> (32 - (i) * 8)) & 0xFF; - - return picodlp_i2c_write_block(client, data, 5); -} - -static int picodlp_i2c_write_array(struct i2c_client *client, - const struct picodlp_i2c_command commands[], - int count) -{ - int i, r = 0; - for (i = 0; i < count; i++) { - r = picodlp_i2c_write(client, commands[i].reg, - commands[i].value); - if (r) - return r; - } - return r; -} - -static int picodlp_wait_for_dma_done(struct i2c_client *client) -{ - u8 trial = 100; - - do { - msleep(1); - if (!trial--) - return -ETIMEDOUT; - } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS); - - return 0; -} - -/** - * picodlp_i2c_init: i2c_initialization routine - * client: i2c_client for communication - * - * return - * 0 : Success, no error - * error code : Failure - */ -static int picodlp_i2c_init(struct i2c_client *client) -{ - int r; - static const struct picodlp_i2c_command init_cmd_set1[] = { - {SOFT_RESET, 1}, - {DMD_PARK_TRIGGER, 1}, - {MISC_REG, 5}, - {SEQ_CONTROL, 0}, - {SEQ_VECTOR, 0x100}, - {DMD_BLOCK_COUNT, 7}, - {DMD_VCC_CONTROL, 0x109}, - {DMD_PARK_PULSE_COUNT, 0xA}, - {DMD_PARK_PULSE_WIDTH, 0xB}, - {DMD_PARK_DELAY, 0x2ED}, - {DMD_SHADOW_ENABLE, 0}, - {FLASH_OPCODE, 0xB}, - {FLASH_DUMMY_BYTES, 1}, - {FLASH_ADDR_BYTES, 3}, - {PBC_CONTROL, 0}, - {FLASH_START_ADDR, CMT_LUT_0_START_ADDR}, - {FLASH_READ_BYTES, CMT_LUT_0_SIZE}, - {CMT_SPLASH_LUT_START_ADDR, 0}, - {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL}, - {PBC_CONTROL, 1}, - }; - - static const struct picodlp_i2c_command init_cmd_set2[] = { - {PBC_CONTROL, 0}, - {CMT_SPLASH_LUT_DEST_SELECT, 0}, - {PBC_CONTROL, 0}, - {FLASH_START_ADDR, SEQUENCE_0_START_ADDR}, - {FLASH_READ_BYTES, SEQUENCE_0_SIZE}, - {SEQ_RESET_LUT_START_ADDR, 0}, - {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT}, - {PBC_CONTROL, 1}, - }; - - static const struct picodlp_i2c_command init_cmd_set3[] = { - {PBC_CONTROL, 0}, - {SEQ_RESET_LUT_DEST_SELECT, 0}, - {PBC_CONTROL, 0}, - {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR}, - {FLASH_READ_BYTES, DRC_TABLE_0_SIZE}, - {SEQ_RESET_LUT_START_ADDR, 0}, - {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL}, - {PBC_CONTROL, 1}, - }; - - static const struct picodlp_i2c_command init_cmd_set4[] = { - {PBC_CONTROL, 0}, - {SEQ_RESET_LUT_DEST_SELECT, 0}, - {SDC_ENABLE, 1}, - {AGC_CTRL, 7}, - {CCA_C1A, 0x100}, - {CCA_C1B, 0x0}, - {CCA_C1C, 0x0}, - {CCA_C2A, 0x0}, - {CCA_C2B, 0x100}, - {CCA_C2C, 0x0}, - {CCA_C3A, 0x0}, - {CCA_C3B, 0x0}, - {CCA_C3C, 0x100}, - {CCA_C7A, 0x100}, - {CCA_C7B, 0x100}, - {CCA_C7C, 0x100}, - {CCA_ENABLE, 1}, - {CPU_IF_MODE, 1}, - {SHORT_FLIP, 1}, - {CURTAIN_CONTROL, 0}, - {DMD_PARK_TRIGGER, 0}, - {R_DRIVE_CURRENT, 0x298}, - {G_DRIVE_CURRENT, 0x298}, - {B_DRIVE_CURRENT, 0x298}, - {RGB_DRIVER_ENABLE, 7}, - {SEQ_CONTROL, 0}, - {ACTGEN_CONTROL, 0x10}, - {SEQUENCE_MODE, SEQ_LOCK}, - {DATA_FORMAT, RGB888}, - {INPUT_RESOLUTION, WVGA_864_LANDSCAPE}, - {INPUT_SOURCE, PARALLEL_RGB}, - {CPU_IF_SYNC_METHOD, 1}, - {SEQ_CONTROL, 1} - }; - - r = picodlp_i2c_write_array(client, init_cmd_set1, - ARRAY_SIZE(init_cmd_set1)); - if (r) - return r; - - r = picodlp_wait_for_dma_done(client); - if (r) - return r; - - r = picodlp_i2c_write_array(client, init_cmd_set2, - ARRAY_SIZE(init_cmd_set2)); - if (r) - return r; - - r = picodlp_wait_for_dma_done(client); - if (r) - return r; - - r = picodlp_i2c_write_array(client, init_cmd_set3, - ARRAY_SIZE(init_cmd_set3)); - if (r) - return r; - - r = picodlp_wait_for_dma_done(client); - if (r) - return r; - - r = picodlp_i2c_write_array(client, init_cmd_set4, - ARRAY_SIZE(init_cmd_set4)); - if (r) - return r; - - return 0; -} - -static int picodlp_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct picodlp_i2c_data *picodlp_i2c_data; - - picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL); - - if (!picodlp_i2c_data) - return -ENOMEM; - - mutex_init(&picodlp_i2c_data->xfer_lock); - i2c_set_clientdata(client, picodlp_i2c_data); - - return 0; -} - -static int picodlp_i2c_remove(struct i2c_client *client) -{ - struct picodlp_i2c_data *picodlp_i2c_data = - i2c_get_clientdata(client); - kfree(picodlp_i2c_data); - return 0; -} - -static struct i2c_driver picodlp_i2c_driver = { - .driver = { - .name = "picodlp_i2c_driver", - }, - .probe = picodlp_i2c_probe, - .remove = picodlp_i2c_remove, - .id_table = picodlp_i2c_id, -}; - -static int picodlp_panel_power_on(struct omap_dss_device *dssdev) -{ - int r, trial = 100; - struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); - struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); - - if (dssdev->platform_enable) { - r = dssdev->platform_enable(dssdev); - if (r) - return r; - } - - gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); - msleep(1); - gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); - - while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) { - if (!trial--) { - dev_err(&dssdev->dev, "emu_done signal not" - " going high\n"); - return -ETIMEDOUT; - } - msleep(5); - } - /* - * As per dpp2600 programming guide, - * it is required to sleep for 510ms after emu_done signal goes high - * then only i2c commands can be successfully sent to dpp2600 - */ - msleep(510); - if (omapdss_dpi_display_enable(dssdev)) { - dev_err(&dssdev->dev, "failed to enable DPI\n"); - goto err1; - } - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - - r = picodlp_i2c_init(picod->picodlp_i2c_client); - if (r) - goto err; - - return r; -err: - omapdss_dpi_display_disable(dssdev); -err1: - if (dssdev->platform_disable) - dssdev->platform_disable(dssdev); - - return r; -} - -static void picodlp_panel_power_off(struct omap_dss_device *dssdev) -{ - struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); - - omapdss_dpi_display_disable(dssdev); - - gpio_set_value(picodlp_pdata->emu_done_gpio, 0); - gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); - - if (dssdev->platform_disable) - dssdev->platform_disable(dssdev); -} - -static int picodlp_panel_probe(struct omap_dss_device *dssdev) -{ - struct picodlp_data *picod; - struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); - struct i2c_adapter *adapter; - struct i2c_client *picodlp_i2c_client; - int r = 0, picodlp_adapter_id; - - dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF | - OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS; - dssdev->panel.acb = 0x0; - dssdev->panel.timings = pico_ls_timings; - - picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL); - if (!picod) - return -ENOMEM; - - mutex_init(&picod->lock); - - picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id; - - adapter = i2c_get_adapter(picodlp_adapter_id); - if (!adapter) { - dev_err(&dssdev->dev, "can't get i2c adapter\n"); - r = -ENODEV; - goto err; - } - - picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); - if (!picodlp_i2c_client) { - dev_err(&dssdev->dev, "can't add i2c device::" - " picodlp_i2c_client is NULL\n"); - r = -ENODEV; - goto err; - } - - picod->picodlp_i2c_client = picodlp_i2c_client; - - dev_set_drvdata(&dssdev->dev, picod); - return r; -err: - kfree(picod); - return r; -} - -static void picodlp_panel_remove(struct omap_dss_device *dssdev) -{ - struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); - - i2c_unregister_device(picod->picodlp_i2c_client); - dev_set_drvdata(&dssdev->dev, NULL); - dev_dbg(&dssdev->dev, "removing picodlp panel\n"); - - kfree(picod); -} - -static int picodlp_panel_enable(struct omap_dss_device *dssdev) -{ - struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); - int r; - - dev_dbg(&dssdev->dev, "enabling picodlp panel\n"); - - mutex_lock(&picod->lock); - if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { - mutex_unlock(&picod->lock); - return -EINVAL; - } - - r = picodlp_panel_power_on(dssdev); - mutex_unlock(&picod->lock); - - return r; -} - -static void picodlp_panel_disable(struct omap_dss_device *dssdev) -{ - struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); - - mutex_lock(&picod->lock); - /* Turn off DLP Power */ - if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) - picodlp_panel_power_off(dssdev); - - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; - mutex_unlock(&picod->lock); - - dev_dbg(&dssdev->dev, "disabling picodlp panel\n"); -} - -static int picodlp_panel_suspend(struct omap_dss_device *dssdev) -{ - struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); - - mutex_lock(&picod->lock); - /* Turn off DLP Power */ - if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { - mutex_unlock(&picod->lock); - dev_err(&dssdev->dev, "unable to suspend picodlp panel," - " panel is not ACTIVE\n"); - return -EINVAL; - } - - picodlp_panel_power_off(dssdev); - - dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; - mutex_unlock(&picod->lock); - - dev_dbg(&dssdev->dev, "suspending picodlp panel\n"); - return 0; -} - -static int picodlp_panel_resume(struct omap_dss_device *dssdev) -{ - struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); - int r; - - mutex_lock(&picod->lock); - if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { - mutex_unlock(&picod->lock); - dev_err(&dssdev->dev, "unable to resume picodlp panel," - " panel is not ACTIVE\n"); - return -EINVAL; - } - - r = picodlp_panel_power_on(dssdev); - mutex_unlock(&picod->lock); - dev_dbg(&dssdev->dev, "resuming picodlp panel\n"); - return r; -} - -static void picodlp_get_resolution(struct omap_dss_device *dssdev, - u16 *xres, u16 *yres) -{ - *xres = dssdev->panel.timings.x_res; - *yres = dssdev->panel.timings.y_res; -} - -static struct omap_dss_driver picodlp_driver = { - .probe = picodlp_panel_probe, - .remove = picodlp_panel_remove, - - .enable = picodlp_panel_enable, - .disable = picodlp_panel_disable, - - .get_resolution = picodlp_get_resolution, - - .suspend = picodlp_panel_suspend, - .resume = picodlp_panel_resume, - - .driver = { - .name = "picodlp_panel", - .owner = THIS_MODULE, - }, -}; - -static int __init picodlp_init(void) -{ - int r = 0; - - r = i2c_add_driver(&picodlp_i2c_driver); - if (r) { - printk(KERN_WARNING "picodlp_i2c_driver" \ - " registration failed\n"); - return r; - } - - r = omap_dss_register_driver(&picodlp_driver); - if (r) - i2c_del_driver(&picodlp_i2c_driver); - - return r; -} - -static void __exit picodlp_exit(void) -{ - i2c_del_driver(&picodlp_i2c_driver); - omap_dss_unregister_driver(&picodlp_driver); -} - -module_init(picodlp_init); -module_exit(picodlp_exit); - -MODULE_AUTHOR("Mythri P K <mythripk@ti.com>"); -MODULE_DESCRIPTION("picodlp driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h deleted file mode 100644 index a34b431a726..00000000000 --- a/drivers/video/omap2/displays/panel-picodlp.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Header file required by picodlp panel driver - * - * Copyright (C) 2009-2011 Texas Instruments - * Author: Mythri P K <mythripk@ti.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H -#define __OMAP2_DISPLAY_PANEL_PICODLP_H - -/* Commands used for configuring picodlp panel */ - -#define MAIN_STATUS 0x03 -#define PBC_CONTROL 0x08 -#define INPUT_SOURCE 0x0B -#define INPUT_RESOLUTION 0x0C -#define DATA_FORMAT 0x0D -#define IMG_ROTATION 0x0E -#define LONG_FLIP 0x0F -#define SHORT_FLIP 0x10 -#define TEST_PAT_SELECT 0x11 -#define R_DRIVE_CURRENT 0x12 -#define G_DRIVE_CURRENT 0x13 -#define B_DRIVE_CURRENT 0x14 -#define READ_REG_SELECT 0x15 -#define RGB_DRIVER_ENABLE 0x16 - -#define CPU_IF_MODE 0x18 -#define FRAME_RATE 0x19 -#define CPU_IF_SYNC_METHOD 0x1A -#define CPU_IF_SOF 0x1B -#define CPU_IF_EOF 0x1C -#define CPU_IF_SLEEP 0x1D - -#define SEQUENCE_MODE 0x1E -#define SOFT_RESET 0x1F -#define FRONT_END_RESET 0x21 -#define AUTO_PWR_ENABLE 0x22 - -#define VSYNC_LINE_DELAY 0x23 -#define CPU_PI_HORIZ_START 0x24 -#define CPU_PI_VERT_START 0x25 -#define CPU_PI_HORIZ_WIDTH 0x26 -#define CPU_PI_VERT_HEIGHT 0x27 - -#define PIXEL_MASK_CROP 0x28 -#define CROP_FIRST_LINE 0x29 -#define CROP_LAST_LINE 0x2A -#define CROP_FIRST_PIXEL 0x2B -#define CROP_LAST_PIXEL 0x2C -#define DMD_PARK_TRIGGER 0x2D - -#define MISC_REG 0x30 - -/* AGC registers */ -#define AGC_CTRL 0x50 -#define AGC_CLIPPED_PIXS 0x55 -#define AGC_BRIGHT_PIXS 0x56 -#define AGC_BG_PIXS 0x57 -#define AGC_SAFETY_MARGIN 0x17 - -/* Color Coordinate Adjustment registers */ -#define CCA_ENABLE 0x5E -#define CCA_C1A 0x5F -#define CCA_C1B 0x60 -#define CCA_C1C 0x61 -#define CCA_C2A 0x62 -#define CCA_C2B 0x63 -#define CCA_C2C 0x64 -#define CCA_C3A 0x65 -#define CCA_C3B 0x66 -#define CCA_C3C 0x67 -#define CCA_C7A 0x71 -#define CCA_C7B 0x72 -#define CCA_C7C 0x73 - -/** - * DLP Pico Processor 2600 comes with flash - * We can do DMA operations from flash for accessing Look Up Tables - */ -#define DMA_STATUS 0x100 -#define FLASH_ADDR_BYTES 0x74 -#define FLASH_DUMMY_BYTES 0x75 -#define FLASH_WRITE_BYTES 0x76 -#define FLASH_READ_BYTES 0x77 -#define FLASH_OPCODE 0x78 -#define FLASH_START_ADDR 0x79 -#define FLASH_DUMMY2 0x7A -#define FLASH_WRITE_DATA 0x7B - -#define TEMPORAL_DITH_DISABLE 0x7E -#define SEQ_CONTROL 0x82 -#define SEQ_VECTOR 0x83 - -/* DMD is Digital Micromirror Device */ -#define DMD_BLOCK_COUNT 0x84 -#define DMD_VCC_CONTROL 0x86 -#define DMD_PARK_PULSE_COUNT 0x87 -#define DMD_PARK_PULSE_WIDTH 0x88 -#define DMD_PARK_DELAY 0x89 -#define DMD_SHADOW_ENABLE 0x8E -#define SEQ_STATUS 0x8F -#define FLASH_CLOCK_CONTROL 0x98 -#define DMD_PARK 0x2D - -#define SDRAM_BIST_ENABLE 0x46 -#define DDR_DRIVER_STRENGTH 0x9A -#define SDC_ENABLE 0x9D -#define SDC_BUFF_SWAP_DISABLE 0xA3 -#define CURTAIN_CONTROL 0xA6 -#define DDR_BUS_SWAP_ENABLE 0xA7 -#define DMD_TRC_ENABLE 0xA8 -#define DMD_BUS_SWAP_ENABLE 0xA9 - -#define ACTGEN_ENABLE 0xAE -#define ACTGEN_CONTROL 0xAF -#define ACTGEN_HORIZ_BP 0xB0 -#define ACTGEN_VERT_BP 0xB1 - -/* Look Up Table access */ -#define CMT_SPLASH_LUT_START_ADDR 0xFA -#define CMT_SPLASH_LUT_DEST_SELECT 0xFB -#define CMT_SPLASH_LUT_DATA 0xFC -#define SEQ_RESET_LUT_START_ADDR 0xFD -#define SEQ_RESET_LUT_DEST_SELECT 0xFE -#define SEQ_RESET_LUT_DATA 0xFF - -/* Input source definitions */ -#define PARALLEL_RGB 0 -#define INT_TEST_PATTERN 1 -#define SPLASH_SCREEN 2 -#define CPU_INTF 3 -#define BT656 4 - -/* Standard input resolution definitions */ -#define QWVGA_LANDSCAPE 3 /* (427h*240v) */ -#define WVGA_864_LANDSCAPE 21 /* (864h*480v) */ -#define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */ - -/* Standard data format definitions */ -#define RGB565 0 -#define RGB666 1 -#define RGB888 2 - -/* Test Pattern definitions */ -#define TPG_CHECKERBOARD 0 -#define TPG_BLACK 1 -#define TPG_WHITE 2 -#define TPG_RED 3 -#define TPG_BLUE 4 -#define TPG_GREEN 5 -#define TPG_VLINES_BLACK 6 -#define TPG_HLINES_BLACK 7 -#define TPG_VLINES_ALT 8 -#define TPG_HLINES_ALT 9 -#define TPG_DIAG_LINES 10 -#define TPG_GREYRAMP_VERT 11 -#define TPG_GREYRAMP_HORIZ 12 -#define TPG_ANSI_CHECKERBOARD 13 - -/* sequence mode definitions */ -#define SEQ_FREE_RUN 0 -#define SEQ_LOCK 1 - -/* curtain color definitions */ -#define CURTAIN_BLACK 0 -#define CURTAIN_RED 1 -#define CURTAIN_GREEN 2 -#define CURTAIN_BLUE 3 -#define CURTAIN_YELLOW 4 -#define CURTAIN_MAGENTA 5 -#define CURTAIN_CYAN 6 -#define CURTAIN_WHITE 7 - -/* LUT definitions */ -#define CMT_LUT_NONE 0 -#define CMT_LUT_GREEN 1 -#define CMT_LUT_RED 2 -#define CMT_LUT_BLUE 3 -#define CMT_LUT_ALL 4 -#define SPLASH_LUT 5 - -#define SEQ_LUT_NONE 0 -#define SEQ_DRC_LUT_0 1 -#define SEQ_DRC_LUT_1 2 -#define SEQ_DRC_LUT_2 3 -#define SEQ_DRC_LUT_3 4 -#define SEQ_SEQ_LUT 5 -#define SEQ_DRC_LUT_ALL 6 -#define WPC_PROGRAM_LUT 7 - -#define BITSTREAM_START_ADDR 0x00000000 -#define BITSTREAM_SIZE 0x00040000 - -#define WPC_FW_0_START_ADDR 0x00040000 -#define WPC_FW_0_SIZE 0x00000ce8 - -#define SEQUENCE_0_START_ADDR 0x00044000 -#define SEQUENCE_0_SIZE 0x00001000 - -#define SEQUENCE_1_START_ADDR 0x00045000 -#define SEQUENCE_1_SIZE 0x00000d10 - -#define SEQUENCE_2_START_ADDR 0x00046000 -#define SEQUENCE_2_SIZE 0x00000d10 - -#define SEQUENCE_3_START_ADDR 0x00047000 -#define SEQUENCE_3_SIZE 0x00000d10 - -#define SEQUENCE_4_START_ADDR 0x00048000 -#define SEQUENCE_4_SIZE 0x00000d10 - -#define SEQUENCE_5_START_ADDR 0x00049000 -#define SEQUENCE_5_SIZE 0x00000d10 - -#define SEQUENCE_6_START_ADDR 0x0004a000 -#define SEQUENCE_6_SIZE 0x00000d10 - -#define CMT_LUT_0_START_ADDR 0x0004b200 -#define CMT_LUT_0_SIZE 0x00000600 - -#define CMT_LUT_1_START_ADDR 0x0004b800 -#define CMT_LUT_1_SIZE 0x00000600 - -#define CMT_LUT_2_START_ADDR 0x0004be00 -#define CMT_LUT_2_SIZE 0x00000600 - -#define CMT_LUT_3_START_ADDR 0x0004c400 -#define CMT_LUT_3_SIZE 0x00000600 - -#define CMT_LUT_4_START_ADDR 0x0004ca00 -#define CMT_LUT_4_SIZE 0x00000600 - -#define CMT_LUT_5_START_ADDR 0x0004d000 -#define CMT_LUT_5_SIZE 0x00000600 - -#define CMT_LUT_6_START_ADDR 0x0004d600 -#define CMT_LUT_6_SIZE 0x00000600 - -#define DRC_TABLE_0_START_ADDR 0x0004dc00 -#define DRC_TABLE_0_SIZE 0x00000100 - -#define SPLASH_0_START_ADDR 0x0004dd00 -#define SPLASH_0_SIZE 0x00032280 - -#define SEQUENCE_7_START_ADDR 0x00080000 -#define SEQUENCE_7_SIZE 0x00000d10 - -#define SEQUENCE_8_START_ADDR 0x00081800 -#define SEQUENCE_8_SIZE 0x00000d10 - -#define SEQUENCE_9_START_ADDR 0x00083000 -#define SEQUENCE_9_SIZE 0x00000d10 - -#define CMT_LUT_7_START_ADDR 0x0008e000 -#define CMT_LUT_7_SIZE 0x00000600 - -#define CMT_LUT_8_START_ADDR 0x0008e800 -#define CMT_LUT_8_SIZE 0x00000600 - -#define CMT_LUT_9_START_ADDR 0x0008f000 -#define CMT_LUT_9_SIZE 0x00000600 - -#define SPLASH_1_START_ADDR 0x0009a000 -#define SPLASH_1_SIZE 0x00032280 - -#define SPLASH_2_START_ADDR 0x000cd000 -#define SPLASH_2_SIZE 0x00032280 - -#define SPLASH_3_START_ADDR 0x00100000 -#define SPLASH_3_SIZE 0x00032280 - -#define OPT_SPLASH_0_START_ADDR 0x00134000 -#define OPT_SPLASH_0_SIZE 0x000cb100 - -#endif diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 4cb0449d509..fdd5d4ae437 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -504,18 +504,14 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev) return 0; r = omapdss_dsi_display_enable(dssdev); - if (r) { - dev_err(&dssdev->dev, "failed to enable DSI\n"); - goto err1; - } + if (r) + goto err; omapdss_dsi_vc_enable_hs(dssdev, td->channel, true); r = _taal_enable_te(dssdev, true); - if (r) { - dev_err(&dssdev->dev, "failed to re-enable TE"); - goto err2; - } + if (r) + goto err; enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); @@ -525,15 +521,13 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev) return 0; -err2: - dev_err(&dssdev->dev, "failed to exit ULPS"); - +err: + dev_err(&dssdev->dev, "exit ULPS failed"); r = taal_panel_reset(dssdev); - if (!r) { - enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); - td->ulps_enabled = false; - } -err1: + + enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); + td->ulps_enabled = false; + taal_queue_ulps_work(dssdev); return r; @@ -1323,11 +1317,8 @@ static void taal_disable(struct omap_dss_device *dssdev) dsi_bus_lock(dssdev); if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { - int r; - - r = taal_wake_up(dssdev); - if (!r) - taal_power_off(dssdev); + taal_wake_up(dssdev); + taal_power_off(dssdev); } dsi_bus_unlock(dssdev); @@ -1906,6 +1897,20 @@ err: mutex_unlock(&td->lock); } +static int taal_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + if (mode != OMAP_DSS_UPDATE_MANUAL) + return -EINVAL; + return 0; +} + +static enum omap_dss_update_mode taal_get_update_mode( + struct omap_dss_device *dssdev) +{ + return OMAP_DSS_UPDATE_MANUAL; +} + static struct omap_dss_driver taal_driver = { .probe = taal_probe, .remove = __exit_p(taal_remove), @@ -1915,6 +1920,9 @@ static struct omap_dss_driver taal_driver = { .suspend = taal_suspend, .resume = taal_resume, + .set_update_mode = taal_set_update_mode, + .get_update_mode = taal_get_update_mode, + .update = taal_update, .sync = taal_sync, diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 0d12524db14..6b3e2da1141 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -117,6 +117,18 @@ config OMAP2_DSS_MIN_FCK_PER_PCK Max FCK is 173MHz, so this doesn't work if your PCK is very high. +config OMAP2_DSS_SLEEP_BEFORE_RESET + bool "Sleep 50ms before DSS reset" + default y + help + For some unknown reason we may get SYNC_LOST errors from the display + subsystem at initialization time if we don't sleep before resetting + the DSS. See the source (dss.c) for more comments. + + However, 50ms is quite long time to sleep, and with some + configurations the SYNC_LOST may never happen, so the sleep can + be disabled here. + config OMAP2_DSS_SLEEP_AFTER_VENC_RESET bool "Sleep 20ms after VENC reset" default y diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index f0bae6d5340..3da426719dd 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -183,11 +183,8 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_dss; } - r = dispc_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize dispc platform driver\n"); - goto err_dispc; - } + /* keep clocks enabled to prevent context saves/restores during init */ + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); r = rfbi_init_platform_driver(); if (r) { @@ -195,6 +192,12 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_rfbi; } + r = dispc_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize dispc platform driver\n"); + goto err_dispc; + } + r = venc_init_platform_driver(); if (r) { DSSERR("Failed to initialize venc platform driver\n"); @@ -235,6 +238,8 @@ static int omap_dss_probe(struct platform_device *pdev) pdata->default_device = dssdev; } + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); + return 0; err_register: diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index eac768ff2d3..7a9a2e7d968 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -33,8 +33,6 @@ #include <linux/workqueue.h> #include <linux/hardirq.h> #include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> #include <plat/sram.h> #include <plat/clock.h> @@ -94,11 +92,7 @@ struct dispc_irq_stats { static struct { struct platform_device *pdev; void __iomem *base; - - int ctx_loss_cnt; - int irq; - struct clk *dss_clk; u32 fifo_size[3]; @@ -108,7 +102,6 @@ static struct { u32 error_irqs; struct work_struct error_work; - bool ctx_valid; u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -141,34 +134,18 @@ static inline u32 dispc_read_reg(const u16 idx) return __raw_readl(dispc.base + idx); } -static int dispc_get_ctx_loss_count(void) -{ - struct device *dev = &dispc.pdev->dev; - struct omap_display_platform_data *pdata = dev->platform_data; - struct omap_dss_board_info *board_data = pdata->board_data; - int cnt; - - if (!board_data->get_context_loss_count) - return -ENOENT; - - cnt = board_data->get_context_loss_count(dev); - - WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt); - - return cnt; -} - #define SR(reg) \ dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) #define RR(reg) \ dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)]) -static void dispc_save_context(void) +void dispc_save_context(void) { int i; + if (cpu_is_omap24xx()) + return; - DSSDBG("dispc_save_context\n"); - + SR(SYSCONFIG); SR(IRQENABLE); SR(CONTROL); SR(CONFIG); @@ -181,8 +158,7 @@ static void dispc_save_context(void) SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_GLOBAL_ALPHA)) - SR(GLOBAL_ALPHA); + SR(GLOBAL_ALPHA); SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -212,25 +188,20 @@ static void dispc_save_context(void) SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_CPR)) { - SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); - } + SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { - if (dss_has_feature(FEAT_CPR)) { - SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); - SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); - SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); - } + SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); + SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); + SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); } - if (dss_has_feature(FEAT_PRELOAD)) - SR(OVL_PRELOAD(OMAP_DSS_GFX)); + SR(OVL_PRELOAD(OMAP_DSS_GFX)); /* VID1 */ SR(OVL_BA0(OMAP_DSS_VIDEO1)); @@ -255,10 +226,8 @@ static void dispc_save_context(void) for (i = 0; i < 5; i++) SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); - } + for (i = 0; i < 8; i++) + SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); @@ -279,8 +248,7 @@ static void dispc_save_context(void) if (dss_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); - if (dss_has_feature(FEAT_PRELOAD)) - SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); + SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); /* VID2 */ SR(OVL_BA0(OMAP_DSS_VIDEO2)); @@ -305,10 +273,8 @@ static void dispc_save_context(void) for (i = 0; i < 5; i++) SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); - } + for (i = 0; i < 8; i++) + SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); @@ -329,35 +295,16 @@ static void dispc_save_context(void) if (dss_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - if (dss_has_feature(FEAT_PRELOAD)) - SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); + SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); if (dss_has_feature(FEAT_CORE_CLK_DIV)) SR(DIVISOR); - - dispc.ctx_loss_cnt = dispc_get_ctx_loss_count(); - dispc.ctx_valid = true; - - DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); } -static void dispc_restore_context(void) +void dispc_restore_context(void) { - int i, ctx; - - DSSDBG("dispc_restore_context\n"); - - if (!dispc.ctx_valid) - return; - - ctx = dispc_get_ctx_loss_count(); - - if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) - return; - - DSSDBG("ctx_loss_count: saved %d, current %d\n", - dispc.ctx_loss_cnt, ctx); - + int i; + RR(SYSCONFIG); /*RR(IRQENABLE);*/ /*RR(CONTROL);*/ RR(CONFIG); @@ -370,8 +317,7 @@ static void dispc_restore_context(void) RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_GLOBAL_ALPHA)) - RR(GLOBAL_ALPHA); + RR(GLOBAL_ALPHA); RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -401,25 +347,20 @@ static void dispc_restore_context(void) RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_CPR)) { - RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); - } + RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); - if (dss_has_feature(FEAT_CPR)) { - RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); - RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); - RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); - } + RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); + RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); + RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); } - if (dss_has_feature(FEAT_PRELOAD)) - RR(OVL_PRELOAD(OMAP_DSS_GFX)); + RR(OVL_PRELOAD(OMAP_DSS_GFX)); /* VID1 */ RR(OVL_BA0(OMAP_DSS_VIDEO1)); @@ -444,10 +385,8 @@ static void dispc_restore_context(void) for (i = 0; i < 5; i++) RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); - } + for (i = 0; i < 8; i++) + RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { RR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); @@ -468,8 +407,7 @@ static void dispc_restore_context(void) if (dss_has_feature(FEAT_ATTR2)) RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); - if (dss_has_feature(FEAT_PRELOAD)) - RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); + RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); /* VID2 */ RR(OVL_BA0(OMAP_DSS_VIDEO2)); @@ -494,10 +432,8 @@ static void dispc_restore_context(void) for (i = 0; i < 5; i++) RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - for (i = 0; i < 8; i++) - RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); - } + for (i = 0; i < 8; i++) + RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); @@ -518,8 +454,7 @@ static void dispc_restore_context(void) if (dss_has_feature(FEAT_ATTR2)) RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - if (dss_has_feature(FEAT_PRELOAD)) - RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); + RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); if (dss_has_feature(FEAT_CORE_CLK_DIV)) RR(DIVISOR); @@ -536,35 +471,19 @@ static void dispc_restore_context(void) * the context is fully restored */ RR(IRQENABLE); - - DSSDBG("context restored\n"); } #undef SR #undef RR -int dispc_runtime_get(void) -{ - int r; - - DSSDBG("dispc_runtime_get\n"); - - r = pm_runtime_get_sync(&dispc.pdev->dev); - WARN_ON(r < 0); - return r < 0 ? r : 0; -} - -void dispc_runtime_put(void) +static inline void enable_clocks(bool enable) { - int r; - - DSSDBG("dispc_runtime_put\n"); - - r = pm_runtime_put(&dispc.pdev->dev); - WARN_ON(r < 0); + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } - bool dispc_go_busy(enum omap_channel channel) { int bit; @@ -586,6 +505,8 @@ void dispc_go(enum omap_channel channel) int bit; bool enable_bit, go_bit; + enable_clocks(1); + if (channel == OMAP_DSS_CHANNEL_LCD || channel == OMAP_DSS_CHANNEL_LCD2) bit = 0; /* LCDENABLE */ @@ -599,7 +520,7 @@ void dispc_go(enum omap_channel channel) enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1; if (!enable_bit) - return; + goto end; if (channel == OMAP_DSS_CHANNEL_LCD || channel == OMAP_DSS_CHANNEL_LCD2) @@ -614,7 +535,7 @@ void dispc_go(enum omap_channel channel) if (go_bit) { DSSERR("GO bit not down for channel %d\n", channel); - return; + goto end; } DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : @@ -624,6 +545,8 @@ void dispc_go(enum omap_channel channel) REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit); else REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); +end: + enable_clocks(0); } static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) @@ -997,7 +920,7 @@ static void _dispc_set_color_mode(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); } -void dispc_set_channel_out(enum omap_plane plane, +static void _dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel) { int shift; @@ -1050,6 +973,8 @@ void dispc_set_burst_size(enum omap_plane plane, int shift; u32 val; + enable_clocks(1); + switch (plane) { case OMAP_DSS_GFX: shift = 6; @@ -1066,6 +991,8 @@ void dispc_set_burst_size(enum omap_plane plane, val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); val = FLD_MOD(val, burst_size, shift+1, shift); dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); + + enable_clocks(0); } void dispc_enable_gamma_table(bool enable) @@ -1102,7 +1029,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable) else bit = 10; + enable_clocks(1); REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); + enable_clocks(0); } void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) @@ -1110,7 +1039,9 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) u32 val; BUG_ON((width > (1 << 11)) || (height > (1 << 11))); val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + enable_clocks(1); dispc_write_reg(DISPC_SIZE_MGR(channel), val); + enable_clocks(0); } void dispc_set_digit_size(u16 width, u16 height) @@ -1118,7 +1049,9 @@ void dispc_set_digit_size(u16 width, u16 height) u32 val; BUG_ON((width > (1 << 11)) || (height > (1 << 11))); val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); + enable_clocks(1); dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); + enable_clocks(0); } static void dispc_read_plane_fifo_sizes(void) @@ -1127,6 +1060,8 @@ static void dispc_read_plane_fifo_sizes(void) int plane; u8 start, end; + enable_clocks(1); + dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { @@ -1134,6 +1069,8 @@ static void dispc_read_plane_fifo_sizes(void) start, end); dispc.fifo_size[plane] = size; } + + enable_clocks(0); } u32 dispc_get_plane_fifo_size(enum omap_plane plane) @@ -1148,6 +1085,8 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); + enable_clocks(1); + DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", plane, REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), @@ -1159,12 +1098,18 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), FLD_VAL(high, hi_start, hi_end) | FLD_VAL(low, lo_start, lo_end)); + + enable_clocks(0); } void dispc_enable_fifomerge(bool enable) { + enable_clocks(1); + DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); + + enable_clocks(0); } static void _dispc_set_fir(enum omap_plane plane, @@ -1784,7 +1729,14 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, return dispc_pclk_rate(channel) * vf * hf; } -int dispc_setup_plane(enum omap_plane plane, +void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) +{ + enable_clocks(1); + _dispc_set_channel_out(plane, channel_out); + enable_clocks(0); +} + +static int _dispc_setup_plane(enum omap_plane plane, u32 paddr, u16 screen_width, u16 pos_x, u16 pos_y, u16 width, u16 height, @@ -1792,7 +1744,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_color_mode color_mode, bool ilace, enum omap_dss_rotation_type rotation_type, - u8 rotation, bool mirror, + u8 rotation, int mirror, u8 global_alpha, u8 pre_mult_alpha, enum omap_channel channel, u32 puv_addr) { @@ -1806,14 +1758,6 @@ int dispc_setup_plane(enum omap_plane plane, u16 frame_height = height; unsigned int field_offset = 0; - DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " - "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", - plane, paddr, screen_width, pos_x, pos_y, - width, height, - out_width, out_height, - ilace, color_mode, - rotation, mirror, channel); - if (paddr == 0) return -EINVAL; @@ -1959,13 +1903,9 @@ int dispc_setup_plane(enum omap_plane plane, return 0; } -int dispc_enable_plane(enum omap_plane plane, bool enable) +static void _dispc_enable_plane(enum omap_plane plane, bool enable) { - DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); - - return 0; } static void dispc_disable_isr(void *data, u32 mask) @@ -1989,6 +1929,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) int r; u32 irq; + enable_clocks(1); + /* When we disable LCD output, we need to wait until frame is done. * Otherwise the DSS is still working, and turning off the clocks * prevents DSS from going to OFF mode */ @@ -2022,6 +1964,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) if (r) DSSERR("failed to unregister FRAMEDONE isr\n"); } + + enable_clocks(0); } static void _enable_digit_out(bool enable) @@ -2034,8 +1978,12 @@ static void dispc_enable_digit_out(bool enable) struct completion frame_done_completion; int r; - if (REG_GET(DISPC_CONTROL, 1, 1) == enable) + enable_clocks(1); + + if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { + enable_clocks(0); return; + } if (enable) { unsigned long flags; @@ -2087,6 +2035,8 @@ static void dispc_enable_digit_out(bool enable) _omap_dispc_set_irqs(); spin_unlock_irqrestore(&dispc.irq_lock, flags); } + + enable_clocks(0); } bool dispc_is_channel_enabled(enum omap_channel channel) @@ -2117,7 +2067,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high) if (!dss_has_feature(FEAT_LCDENABLEPOL)) return; + enable_clocks(1); REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); + enable_clocks(0); } void dispc_lcd_enable_signal(bool enable) @@ -2125,7 +2077,9 @@ void dispc_lcd_enable_signal(bool enable) if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) return; + enable_clocks(1); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); + enable_clocks(0); } void dispc_pck_free_enable(bool enable) @@ -2133,15 +2087,19 @@ void dispc_pck_free_enable(bool enable) if (!dss_has_feature(FEAT_PCKFREEENABLE)) return; + enable_clocks(1); REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); + enable_clocks(0); } void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) { + enable_clocks(1); if (channel == OMAP_DSS_CHANNEL_LCD2) REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); else REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); + enable_clocks(0); } @@ -2164,21 +2122,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel, return; } + enable_clocks(1); if (channel == OMAP_DSS_CHANNEL_LCD2) REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3); else REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); + enable_clocks(0); } void dispc_set_loadmode(enum omap_dss_load_mode mode) { + enable_clocks(1); REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); + enable_clocks(0); } void dispc_set_default_color(enum omap_channel channel, u32 color) { + enable_clocks(1); dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); + enable_clocks(0); } u32 dispc_get_default_color(enum omap_channel channel) @@ -2189,7 +2153,9 @@ u32 dispc_get_default_color(enum omap_channel channel) channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2); + enable_clocks(1); l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); + enable_clocks(0); return l; } @@ -2198,6 +2164,7 @@ void dispc_set_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type type, u32 trans_key) { + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2206,12 +2173,14 @@ void dispc_set_trans_key(enum omap_channel ch, REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11); dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); + enable_clocks(0); } void dispc_get_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type *type, u32 *trans_key) { + enable_clocks(1); if (type) { if (ch == OMAP_DSS_CHANNEL_LCD) *type = REG_GET(DISPC_CONFIG, 11, 11); @@ -2225,28 +2194,33 @@ void dispc_get_trans_key(enum omap_channel ch, if (trans_key) *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); + enable_clocks(0); } void dispc_enable_trans_key(enum omap_channel ch, bool enable) { + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); else if (ch == OMAP_DSS_CHANNEL_DIGIT) REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); else /* OMAP_DSS_CHANNEL_LCD2 */ REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); + enable_clocks(0); } void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) { if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) return; + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); else if (ch == OMAP_DSS_CHANNEL_DIGIT) REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); else /* OMAP_DSS_CHANNEL_LCD2 */ REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18); + enable_clocks(0); } bool dispc_alpha_blending_enabled(enum omap_channel ch) { @@ -2255,6 +2229,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch) if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) return false; + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) enabled = REG_GET(DISPC_CONFIG, 18, 18); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2263,6 +2238,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch) enabled = REG_GET(DISPC_CONFIG2, 18, 18); else BUG(); + enable_clocks(0); return enabled; } @@ -2272,6 +2248,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) { bool enabled; + enable_clocks(1); if (ch == OMAP_DSS_CHANNEL_LCD) enabled = REG_GET(DISPC_CONFIG, 10, 10); else if (ch == OMAP_DSS_CHANNEL_DIGIT) @@ -2280,6 +2257,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) enabled = REG_GET(DISPC_CONFIG2, 10, 10); else BUG(); + enable_clocks(0); return enabled; } @@ -2307,10 +2285,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) return; } + enable_clocks(1); if (channel == OMAP_DSS_CHANNEL_LCD2) REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8); else REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); + enable_clocks(0); } void dispc_set_parallel_interface_mode(enum omap_channel channel, @@ -2342,6 +2322,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel, return; } + enable_clocks(1); + if (channel == OMAP_DSS_CHANNEL_LCD2) { l = dispc_read_reg(DISPC_CONTROL2); l = FLD_MOD(l, stallmode, 11, 11); @@ -2353,6 +2335,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel, l = FLD_MOD(l, gpout1, 16, 16); dispc_write_reg(DISPC_CONTROL, l); } + + enable_clocks(0); } static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, @@ -2405,8 +2389,10 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, FLD_VAL(vbp, 31, 20); } + enable_clocks(1); dispc_write_reg(DISPC_TIMING_H(channel), timing_h); dispc_write_reg(DISPC_TIMING_V(channel), timing_v); + enable_clocks(0); } /* change name to mode? */ @@ -2449,8 +2435,10 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, BUG_ON(lck_div < 1); BUG_ON(pck_div < 2); + enable_clocks(1); dispc_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); + enable_clocks(0); } static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, @@ -2469,7 +2457,7 @@ unsigned long dispc_fclk_rate(void) switch (dss_get_dispc_clk_source()) { case OMAP_DSS_CLK_SRC_FCK: - r = clk_get_rate(dispc.dss_clk); + r = dss_clk_get_rate(DSS_CLK_FCK); break; case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: dsidev = dsi_get_dsidev_from_id(0); @@ -2499,7 +2487,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) switch (dss_get_lcd_clk_source(channel)) { case OMAP_DSS_CLK_SRC_FCK: - r = clk_get_rate(dispc.dss_clk); + r = dss_clk_get_rate(DSS_CLK_FCK); break; case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: dsidev = dsi_get_dsidev_from_id(0); @@ -2538,8 +2526,7 @@ void dispc_dump_clocks(struct seq_file *s) enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); enum omap_dss_clk_source lcd_clk_src; - if (dispc_runtime_get()) - return; + enable_clocks(1); seq_printf(s, "- DISPC -\n"); @@ -2587,8 +2574,7 @@ void dispc_dump_clocks(struct seq_file *s) seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); } - - dispc_runtime_put(); + enable_clocks(0); } #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -2643,8 +2629,7 @@ void dispc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) - if (dispc_runtime_get()) - return; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DISPC_REVISION); DUMPREG(DISPC_SYSCONFIG); @@ -2664,8 +2649,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD)); DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_GLOBAL_ALPHA)) - DUMPREG(DISPC_GLOBAL_ALPHA); + DUMPREG(DISPC_GLOBAL_ALPHA); DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -2696,25 +2680,20 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - if (dss_has_feature(FEAT_CPR)) { - DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); - } + DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); - if (dss_has_feature(FEAT_CPR)) { - DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); - DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); - DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); - } + DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); + DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); + DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); } - if (dss_has_feature(FEAT_PRELOAD)) - DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); + DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); @@ -2765,16 +2744,14 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); - } + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1)); @@ -2835,17 +2812,14 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3)); DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4)); - - if (dss_has_feature(FEAT_FIR_COEF_V)) { - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); - DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); - } + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); + DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2)); @@ -2884,12 +2858,10 @@ void dispc_dump_regs(struct seq_file *s) if (dss_has_feature(FEAT_ATTR2)) DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - if (dss_has_feature(FEAT_PRELOAD)) { - DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); - DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); - } + DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); + DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); - dispc_runtime_put(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -2910,7 +2882,9 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, l |= FLD_VAL(acbi, 11, 8); l |= FLD_VAL(acb, 7, 0); + enable_clocks(1); dispc_write_reg(DISPC_POL_FREQ(channel), l); + enable_clocks(0); } void dispc_set_pol_freq(enum omap_channel channel, @@ -3031,11 +3005,15 @@ static void _omap_dispc_set_irqs(void) mask |= isr_data->mask; } + enable_clocks(1); + old_mask = dispc_read_reg(DISPC_IRQENABLE); /* clear the irqstatus for newly enabled irqs */ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask); dispc_write_reg(DISPC_IRQENABLE, mask); + + enable_clocks(0); } int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) @@ -3544,6 +3522,13 @@ static void _omap_dispc_initial_config(void) { u32 l; + l = dispc_read_reg(DISPC_SYSCONFIG); + l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */ + l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */ + l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */ + l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ + dispc_write_reg(DISPC_SYSCONFIG, l); + /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ if (dss_has_feature(FEAT_CORE_CLK_DIV)) { l = dispc_read_reg(DISPC_DIVISOR); @@ -3569,25 +3554,67 @@ static void _omap_dispc_initial_config(void) dispc_read_plane_fifo_sizes(); } +int dispc_enable_plane(enum omap_plane plane, bool enable) +{ + DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); + + enable_clocks(1); + _dispc_enable_plane(plane, enable); + enable_clocks(0); + + return 0; +} + +int dispc_setup_plane(enum omap_plane plane, + u32 paddr, u16 screen_width, + u16 pos_x, u16 pos_y, + u16 width, u16 height, + u16 out_width, u16 out_height, + enum omap_color_mode color_mode, + bool ilace, + enum omap_dss_rotation_type rotation_type, + u8 rotation, bool mirror, u8 global_alpha, + u8 pre_mult_alpha, enum omap_channel channel, + u32 puv_addr) +{ + int r = 0; + + DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> " + "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", + plane, paddr, screen_width, pos_x, pos_y, + width, height, + out_width, out_height, + ilace, color_mode, + rotation, mirror, channel); + + enable_clocks(1); + + r = _dispc_setup_plane(plane, + paddr, screen_width, + pos_x, pos_y, + width, height, + out_width, out_height, + color_mode, ilace, + rotation_type, + rotation, mirror, + global_alpha, + pre_mult_alpha, + channel, puv_addr); + + enable_clocks(0); + + return r; +} + /* DISPC HW IP initialisation */ static int omap_dispchw_probe(struct platform_device *pdev) { u32 rev; int r = 0; struct resource *dispc_mem; - struct clk *clk; dispc.pdev = pdev; - clk = clk_get(&pdev->dev, "dss_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get dss_clk\n"); - r = PTR_ERR(clk); - goto err_get_clk; - } - - dispc.dss_clk = clk; - spin_lock_init(&dispc.irq_lock); #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -3601,103 +3628,62 @@ static int omap_dispchw_probe(struct platform_device *pdev) if (!dispc_mem) { DSSERR("can't get IORESOURCE_MEM DISPC\n"); r = -EINVAL; - goto err_ioremap; + goto fail0; } dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); if (!dispc.base) { DSSERR("can't ioremap DISPC\n"); r = -ENOMEM; - goto err_ioremap; + goto fail0; } dispc.irq = platform_get_irq(dispc.pdev, 0); if (dispc.irq < 0) { DSSERR("platform_get_irq failed\n"); r = -ENODEV; - goto err_irq; + goto fail1; } r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, "OMAP DISPC", dispc.pdev); if (r < 0) { DSSERR("request_irq failed\n"); - goto err_irq; + goto fail1; } - pm_runtime_enable(&pdev->dev); - - r = dispc_runtime_get(); - if (r) - goto err_runtime_get; + enable_clocks(1); _omap_dispc_initial_config(); _omap_dispc_initialize_irq(); + dispc_save_context(); + rev = dispc_read_reg(DISPC_REVISION); dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - dispc_runtime_put(); + enable_clocks(0); return 0; - -err_runtime_get: - pm_runtime_disable(&pdev->dev); - free_irq(dispc.irq, dispc.pdev); -err_irq: +fail1: iounmap(dispc.base); -err_ioremap: - clk_put(dispc.dss_clk); -err_get_clk: +fail0: return r; } static int omap_dispchw_remove(struct platform_device *pdev) { - pm_runtime_disable(&pdev->dev); - - clk_put(dispc.dss_clk); - free_irq(dispc.irq, dispc.pdev); iounmap(dispc.base); return 0; } -static int dispc_runtime_suspend(struct device *dev) -{ - dispc_save_context(); - clk_disable(dispc.dss_clk); - dss_runtime_put(); - - return 0; -} - -static int dispc_runtime_resume(struct device *dev) -{ - int r; - - r = dss_runtime_get(); - if (r < 0) - return r; - - clk_enable(dispc.dss_clk); - dispc_restore_context(); - - return 0; -} - -static const struct dev_pm_ops dispc_pm_ops = { - .runtime_suspend = dispc_runtime_suspend, - .runtime_resume = dispc_runtime_resume, -}; - static struct platform_driver omap_dispchw_driver = { .probe = omap_dispchw_probe, .remove = omap_dispchw_remove, .driver = { .name = "omapdss_dispc", .owner = THIS_MODULE, - .pm = &dispc_pm_ops, }, }; diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index a0bbdf6684b..c2dfc8c5005 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -65,6 +65,48 @@ static ssize_t display_enabled_store(struct device *dev, return size; } +static ssize_t display_upd_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO; + if (dssdev->driver->get_update_mode) + mode = dssdev->driver->get_update_mode(dssdev); + return snprintf(buf, PAGE_SIZE, "%d\n", mode); +} + +static ssize_t display_upd_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + int val, r; + enum omap_dss_update_mode mode; + + if (!dssdev->driver->set_update_mode) + return -EINVAL; + + r = kstrtoint(buf, 0, &val); + if (r) + return r; + + switch (val) { + case OMAP_DSS_UPDATE_DISABLED: + case OMAP_DSS_UPDATE_AUTO: + case OMAP_DSS_UPDATE_MANUAL: + mode = (enum omap_dss_update_mode)val; + break; + default: + return -EINVAL; + } + + r = dssdev->driver->set_update_mode(dssdev, mode); + if (r) + return r; + + return size; +} + static ssize_t display_tear_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -252,6 +294,8 @@ static ssize_t display_wss_store(struct device *dev, static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, display_enabled_show, display_enabled_store); +static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR, + display_upd_mode_show, display_upd_mode_store); static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, display_tear_show, display_tear_store); static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, @@ -265,6 +309,7 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, static struct device_attribute *display_sysfs_attrs[] = { &dev_attr_enabled, + &dev_attr_update_mode, &dev_attr_tear_elim, &dev_attr_timings, &dev_attr_rotate, diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index f053b180ecd..ff6bd30132d 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -23,6 +23,7 @@ #define DSS_SUBSYS_NAME "DPI" #include <linux/kernel.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/errno.h> @@ -129,6 +130,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) bool is_tft; int r = 0; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); @@ -141,7 +144,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, &lck_div, &pck_div); if (r) - return r; + goto err0; pck = fck / lck_div / pck_div / 1000; @@ -155,10 +158,12 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) dispc_set_lcd_timings(dssdev->manager->id, t); - return 0; +err0: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); + return r; } -static void dpi_basic_init(struct omap_dss_device *dssdev) +static int dpi_basic_init(struct omap_dss_device *dssdev) { bool is_tft; @@ -170,6 +175,8 @@ static void dpi_basic_init(struct omap_dss_device *dssdev) OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); dispc_set_tft_data_lines(dssdev->manager->id, dssdev->phy.dpi.data_lines); + + return 0; } int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) @@ -179,38 +186,31 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); - goto err_start_dev; + goto err0; } if (cpu_is_omap34xx()) { r = regulator_enable(dpi.vdds_dsi_reg); if (r) - goto err_reg_enable; + goto err1; } - r = dss_runtime_get(); - if (r) - goto err_get_dss; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - r = dispc_runtime_get(); + r = dpi_basic_init(dssdev); if (r) - goto err_get_dispc; - - dpi_basic_init(dssdev); + goto err2; if (dpi_use_dsi_pll(dssdev)) { - r = dsi_runtime_get(dpi.dsidev); - if (r) - goto err_get_dsi; - + dss_clk_enable(DSS_CLK_SYSCK); r = dsi_pll_init(dpi.dsidev, 0, 1); if (r) - goto err_dsi_pll_init; + goto err3; } r = dpi_set_mode(dssdev); if (r) - goto err_set_mode; + goto err4; mdelay(2); @@ -218,22 +218,19 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) return 0; -err_set_mode: +err4: if (dpi_use_dsi_pll(dssdev)) dsi_pll_uninit(dpi.dsidev, true); -err_dsi_pll_init: +err3: if (dpi_use_dsi_pll(dssdev)) - dsi_runtime_put(dpi.dsidev); -err_get_dsi: - dispc_runtime_put(); -err_get_dispc: - dss_runtime_put(); -err_get_dss: + dss_clk_disable(DSS_CLK_SYSCK); +err2: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); -err_reg_enable: +err1: omap_dss_stop_device(dssdev); -err_start_dev: +err0: return r; } EXPORT_SYMBOL(omapdss_dpi_display_enable); @@ -245,11 +242,10 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) if (dpi_use_dsi_pll(dssdev)) { dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dsi_pll_uninit(dpi.dsidev, true); - dsi_runtime_put(dpi.dsidev); + dss_clk_disable(DSS_CLK_SYSCK); } - dispc_runtime_put(); - dss_runtime_put(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); @@ -261,26 +257,11 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable); void dpi_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { - int r; - DSSDBG("dpi_set_timings\n"); dssdev->panel.timings = *timings; if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { - r = dss_runtime_get(); - if (r) - return; - - r = dispc_runtime_get(); - if (r) { - dss_runtime_put(); - return; - } - dpi_set_mode(dssdev); dispc_go(dssdev->manager->id); - - dispc_runtime_put(); - dss_runtime_put(); } } EXPORT_SYMBOL(dpi_set_timings); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index b6a57bb7a61..345757cfcbe 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -36,7 +36,6 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/debugfs.h> -#include <linux/pm_runtime.h> #include <video/omapdss.h> #include <plat/clock.h> @@ -268,12 +267,8 @@ struct dsi_isr_tables { struct dsi_data { struct platform_device *pdev; void __iomem *base; - int irq; - struct clk *dss_clk; - struct clk *sys_clk; - void (*dsi_mux_pads)(bool enable); struct dsi_clock_info current_cinfo; @@ -394,6 +389,15 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev, return __raw_readl(dsi->base + idx.idx); } + +void dsi_save_context(void) +{ +} + +void dsi_restore_context(void) +{ +} + void dsi_bus_lock(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -489,18 +493,9 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) total_bytes * 1000 / total_us); } #else -static inline void dsi_perf_mark_setup(struct platform_device *dsidev) -{ -} - -static inline void dsi_perf_mark_start(struct platform_device *dsidev) -{ -} - -static inline void dsi_perf_show(struct platform_device *dsidev, - const char *name) -{ -} +#define dsi_perf_mark_setup(x) +#define dsi_perf_mark_start(x) +#define dsi_perf_show(x, y) #endif static void print_irq_status(u32 status) @@ -1044,27 +1039,13 @@ static u32 dsi_get_errors(struct platform_device *dsidev) return e; } -int dsi_runtime_get(struct platform_device *dsidev) +/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ +static inline void enable_clocks(bool enable) { - int r; - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - - DSSDBG("dsi_runtime_get\n"); - - r = pm_runtime_get_sync(&dsi->pdev->dev); - WARN_ON(r < 0); - return r < 0 ? r : 0; -} - -void dsi_runtime_put(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - int r; - - DSSDBG("dsi_runtime_put\n"); - - r = pm_runtime_put(&dsi->pdev->dev); - WARN_ON(r < 0); + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } /* source clock for DSI PLL. this could also be PCLKFREE */ @@ -1074,9 +1055,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev, struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); if (enable) - clk_enable(dsi->sys_clk); + dss_clk_enable(DSS_CLK_SYSCK); else - clk_disable(dsi->sys_clk); + dss_clk_disable(DSS_CLK_SYSCK); if (enable && dsi->pll_locked) { if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) @@ -1169,11 +1150,10 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev) { unsigned long r; int dsi_module = dsi_get_dsidev_id(dsidev); - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { /* DSI FCLK source is DSS_CLK_FCK */ - r = clk_get_rate(dsi->dss_clk); + r = dss_clk_get_rate(DSS_CLK_FCK); } else { /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ r = dsi_get_pll_hsdiv_dsi_rate(dsidev); @@ -1282,7 +1262,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, return -EINVAL; if (cinfo->use_sys_clk) { - cinfo->clkin = clk_get_rate(dsi->sys_clk); + cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); /* XXX it is unclear if highfreq should be used * with DSS_SYS_CLK source also */ cinfo->highfreq = 0; @@ -1331,7 +1311,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, int match = 0; unsigned long dss_sys_clk, max_dss_fck; - dss_sys_clk = clk_get_rate(dsi->sys_clk); + dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); @@ -1621,6 +1601,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, dsi->vdds_dsi_reg = vdds_dsi; } + enable_clocks(1); dsi_enable_pll_clock(dsidev, 1); /* * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. @@ -1672,6 +1653,7 @@ err1: } err0: dsi_disable_scp_clk(dsidev); + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); return r; } @@ -1689,6 +1671,7 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes) } dsi_disable_scp_clk(dsidev); + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); DSSDBG("PLL uninit done\n"); @@ -1705,8 +1688,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, dispc_clk_src = dss_get_dispc_clk_source(); dsi_clk_src = dss_get_dsi_clk_source(dsi_module); - if (dsi_runtime_get(dsidev)) - return; + enable_clocks(1); seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); @@ -1749,7 +1731,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); - dsi_runtime_put(dsidev); + enable_clocks(0); } void dsi_dump_clocks(struct seq_file *s) @@ -1891,8 +1873,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev, { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r)) - if (dsi_runtime_get(dsidev)) - return; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); dsi_enable_scp_clk(dsidev); DUMPREG(DSI_REVISION); @@ -1966,7 +1947,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev, DUMPREG(DSI_PLL_CONFIGURATION2); dsi_disable_scp_clk(dsidev); - dsi_runtime_put(dsidev); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -2482,6 +2463,28 @@ static void dsi_cio_uninit(struct platform_device *dsidev) dsi->dsi_mux_pads(false); } +static int _dsi_wait_reset(struct platform_device *dsidev) +{ + int t = 0; + + while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) { + if (++t > 5) { + DSSERR("soft reset failed\n"); + return -ENODEV; + } + udelay(1); + } + + return 0; +} + +static int _dsi_reset(struct platform_device *dsidev) +{ + /* Soft reset */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1); + return _dsi_wait_reset(dsidev); +} + static void dsi_config_tx_fifo(struct platform_device *dsidev, enum fifo_size size1, enum fifo_size size2, enum fifo_size size3, enum fifo_size size4) @@ -3383,10 +3386,6 @@ static int dsi_enter_ulps(struct platform_device *dsidev) dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); - /* Reset LANEx_ULPS_SIG2 */ - REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), - 7, 5); - dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); dsi_if_enable(dsidev, false); @@ -4199,6 +4198,22 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, dsi_pll_uninit(dsidev, disconnect_lanes); } +static int dsi_core_init(struct platform_device *dsidev) +{ + /* Autoidle */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0); + + /* ENWAKEUP */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2); + + /* SIDLEMODE smart-idle */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3); + + _dsi_initialize_irq(dsidev); + + return 0; +} + int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -4214,37 +4229,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); - goto err_start_dev; + goto err0; } - r = dsi_runtime_get(dsidev); - if (r) - goto err_get_dsi; - + enable_clocks(1); dsi_enable_pll_clock(dsidev, 1); - _dsi_initialize_irq(dsidev); + r = _dsi_reset(dsidev); + if (r) + goto err1; + + dsi_core_init(dsidev); r = dsi_display_init_dispc(dssdev); if (r) - goto err_init_dispc; + goto err1; r = dsi_display_init_dsi(dssdev); if (r) - goto err_init_dsi; + goto err2; mutex_unlock(&dsi->lock); return 0; -err_init_dsi: +err2: dsi_display_uninit_dispc(dssdev); -err_init_dispc: +err1: + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); - dsi_runtime_put(dsidev); -err_get_dsi: omap_dss_stop_device(dssdev); -err_start_dev: +err0: mutex_unlock(&dsi->lock); DSSDBG("dsi_display_enable FAILED\n"); return r; @@ -4267,7 +4282,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); - dsi_runtime_put(dsidev); + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); omap_dss_stop_device(dssdev); @@ -4422,44 +4437,7 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev) dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); } -static int dsi_get_clocks(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct clk *clk; - - clk = clk_get(&dsidev->dev, "dss_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get dss_clk\n"); - return PTR_ERR(clk); - } - - dsi->dss_clk = clk; - - clk = clk_get(&dsidev->dev, "sys_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get sys_clk\n"); - clk_put(dsi->dss_clk); - dsi->dss_clk = NULL; - return PTR_ERR(clk); - } - - dsi->sys_clk = clk; - - return 0; -} - -static void dsi_put_clocks(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - - if (dsi->dss_clk) - clk_put(dsi->dss_clk); - if (dsi->sys_clk) - clk_put(dsi->sys_clk); -} - -/* DSI1 HW IP initialisation */ -static int omap_dsi1hw_probe(struct platform_device *dsidev) +static int dsi_init(struct platform_device *dsidev) { struct omap_display_platform_data *dss_plat_data; struct omap_dss_board_info *board_info; @@ -4471,7 +4449,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); if (!dsi) { r = -ENOMEM; - goto err_alloc; + goto err0; } dsi->pdev = dsidev; @@ -4494,12 +4472,6 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) mutex_init(&dsi->lock); sema_init(&dsi->bus_lock, 1); - r = dsi_get_clocks(dsidev); - if (r) - goto err_get_clk; - - pm_runtime_enable(&dsidev->dev); - INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, dsi_framedone_timeout_work_callback); @@ -4512,26 +4484,26 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) if (!dsi_mem) { DSSERR("can't get IORESOURCE_MEM DSI\n"); r = -EINVAL; - goto err_ioremap; + goto err1; } dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); if (!dsi->base) { DSSERR("can't ioremap DSI\n"); r = -ENOMEM; - goto err_ioremap; + goto err1; } dsi->irq = platform_get_irq(dsi->pdev, 0); if (dsi->irq < 0) { DSSERR("platform_get_irq failed\n"); r = -ENODEV; - goto err_get_irq; + goto err2; } r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev); if (r < 0) { DSSERR("request_irq failed\n"); - goto err_get_irq; + goto err2; } /* DSI VCs initialization */ @@ -4543,9 +4515,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) dsi_calc_clock_param_ranges(dsidev); - r = dsi_runtime_get(dsidev); - if (r) - goto err_get_dsi; + enable_clocks(1); rev = dsi_read_reg(dsidev, DSI_REVISION); dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", @@ -4553,32 +4523,21 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); - dsi_runtime_put(dsidev); + enable_clocks(0); return 0; - -err_get_dsi: - free_irq(dsi->irq, dsi->pdev); -err_get_irq: +err2: iounmap(dsi->base); -err_ioremap: - pm_runtime_disable(&dsidev->dev); -err_get_clk: +err1: kfree(dsi); -err_alloc: +err0: return r; } -static int omap_dsi1hw_remove(struct platform_device *dsidev) +static void dsi_exit(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - WARN_ON(dsi->scp_clk_refcount > 0); - - pm_runtime_disable(&dsidev->dev); - - dsi_put_clocks(dsidev); - if (dsi->vdds_dsi_reg != NULL) { if (dsi->vdds_dsi_enabled) { regulator_disable(dsi->vdds_dsi_reg); @@ -4594,56 +4553,38 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev) kfree(dsi); - return 0; + DSSDBG("omap_dsi_exit\n"); } -static int dsi_runtime_suspend(struct device *dev) +/* DSI1 HW IP initialisation */ +static int omap_dsi1hw_probe(struct platform_device *dsidev) { - struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); - - clk_disable(dsi->dss_clk); - - dispc_runtime_put(); - dss_runtime_put(); + int r; - return 0; + r = dsi_init(dsidev); + if (r) { + DSSERR("Failed to initialize DSI\n"); + goto err_dsi; + } +err_dsi: + return r; } -static int dsi_runtime_resume(struct device *dev) +static int omap_dsi1hw_remove(struct platform_device *dsidev) { - struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); - int r; - - r = dss_runtime_get(); - if (r) - goto err_get_dss; - - r = dispc_runtime_get(); - if (r) - goto err_get_dispc; - - clk_enable(dsi->dss_clk); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + dsi_exit(dsidev); + WARN_ON(dsi->scp_clk_refcount > 0); return 0; - -err_get_dispc: - dss_runtime_put(); -err_get_dss: - return r; } -static const struct dev_pm_ops dsi_pm_ops = { - .runtime_suspend = dsi_runtime_suspend, - .runtime_resume = dsi_runtime_resume, -}; - static struct platform_driver omap_dsi1hw_driver = { .probe = omap_dsi1hw_probe, .remove = omap_dsi1hw_remove, .driver = { .name = "omapdss_dsi1", .owner = THIS_MODULE, - .pm = &dsi_pm_ops, }, }; diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 5c6499a4d6a..d9489d5c4f0 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -28,8 +28,6 @@ #include <linux/delay.h> #include <linux/seq_file.h> #include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> #include <video/omapdss.h> #include <plat/clock.h> @@ -61,9 +59,15 @@ struct dss_reg { static struct { struct platform_device *pdev; void __iomem *base; + int ctx_id; struct clk *dpll4_m4_ck; - struct clk *dss_clk; + struct clk *dss_ick; + struct clk *dss_fck; + struct clk *dss_sys_clk; + struct clk *dss_tv_fck; + struct clk *dss_video_fck; + unsigned num_clks_enabled; unsigned long cache_req_pck; unsigned long cache_prate; @@ -74,7 +78,6 @@ static struct { enum omap_dss_clk_source dispc_clk_source; enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; - bool ctx_valid; u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; @@ -84,6 +87,13 @@ static const char * const dss_generic_clk_source_names[] = { [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", }; +static void dss_clk_enable_all_no_ctx(void); +static void dss_clk_disable_all_no_ctx(void); +static void dss_clk_enable_no_ctx(enum dss_clock clks); +static void dss_clk_disable_no_ctx(enum dss_clock clks); + +static int _omap_dss_wait_reset(void); + static inline void dss_write_reg(const struct dss_reg idx, u32 val) { __raw_writel(val, dss.base + idx.idx); @@ -99,10 +109,12 @@ static inline u32 dss_read_reg(const struct dss_reg idx) #define RR(reg) \ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)]) -static void dss_save_context(void) +void dss_save_context(void) { - DSSDBG("dss_save_context\n"); + if (cpu_is_omap24xx()) + return; + SR(SYSCONFIG); SR(CONTROL); if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & @@ -110,19 +122,14 @@ static void dss_save_context(void) SR(SDI_CONTROL); SR(PLL_CONTROL); } - - dss.ctx_valid = true; - - DSSDBG("context saved\n"); } -static void dss_restore_context(void) +void dss_restore_context(void) { - DSSDBG("dss_restore_context\n"); - - if (!dss.ctx_valid) - return; + if (_omap_dss_wait_reset()) + DSSERR("DSS not coming out of reset after sleep\n"); + RR(SYSCONFIG); RR(CONTROL); if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & @@ -130,8 +137,6 @@ static void dss_restore_context(void) RR(SDI_CONTROL); RR(PLL_CONTROL); } - - DSSDBG("context restored\n"); } #undef SR @@ -229,7 +234,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) return dss_generic_clk_source_names[clk_src]; } - void dss_dump_clocks(struct seq_file *s) { unsigned long dpll4_ck_rate; @@ -237,14 +241,13 @@ void dss_dump_clocks(struct seq_file *s) const char *fclk_name, *fclk_real_name; unsigned long fclk_rate; - if (dss_runtime_get()) - return; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); seq_printf(s, "- DSS -\n"); fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); - fclk_rate = clk_get_rate(dss.dss_clk); + fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); if (dss.dpll4_m4_ck) { dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); @@ -270,15 +273,14 @@ void dss_dump_clocks(struct seq_file *s) fclk_rate); } - dss_runtime_put(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } void dss_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) - if (dss_runtime_get()) - return; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DSS_REVISION); DUMPREG(DSS_SYSCONFIG); @@ -292,7 +294,7 @@ void dss_dump_regs(struct seq_file *s) DUMPREG(DSS_SDI_STATUS); } - dss_runtime_put(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -435,7 +437,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo) } else { if (cinfo->fck_div != 0) return -EINVAL; - cinfo->fck = clk_get_rate(dss.dss_clk); + cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); } return 0; @@ -465,7 +467,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) int dss_get_clock_div(struct dss_clock_info *cinfo) { - cinfo->fck = clk_get_rate(dss.dss_clk); + cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); if (dss.dpll4_m4_ck) { unsigned long prate; @@ -510,7 +512,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); - fck = clk_get_rate(dss.dss_clk); + fck = dss_clk_get_rate(DSS_CLK_FCK); if (req_pck == dss.cache_req_pck && ((cpu_is_omap34xx() && prate == dss.cache_prate) || dss.cache_dss_cinfo.fck == fck)) { @@ -537,7 +539,7 @@ retry: if (dss.dpll4_m4_ck == NULL) { struct dispc_clock_info cur_dispc; /* XXX can we change the clock on omap2? */ - fck = clk_get_rate(dss.dss_clk); + fck = dss_clk_get_rate(DSS_CLK_FCK); fck_div = 1; dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); @@ -614,6 +616,28 @@ found: return 0; } +static int _omap_dss_wait_reset(void) +{ + int t = 0; + + while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) { + if (++t > 1000) { + DSSERR("soft reset failed\n"); + return -ENODEV; + } + udelay(1); + } + + return 0; +} + +static int _omap_dss_reset(void) +{ + /* Soft reset */ + REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1); + return _omap_dss_wait_reset(); +} + void dss_set_venc_output(enum omap_dss_venc_type type) { int l = 0; @@ -639,83 +663,424 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ } -static int dss_get_clocks(void) +static int dss_init(void) { - struct clk *clk; int r; + u32 rev; + struct resource *dss_mem; + struct clk *dpll4_m4_ck; - clk = clk_get(&dss.pdev->dev, "dss_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get clock dss_clk\n"); - r = PTR_ERR(clk); - goto err; + dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); + if (!dss_mem) { + DSSERR("can't get IORESOURCE_MEM DSS\n"); + r = -EINVAL; + goto fail0; + } + dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); + if (!dss.base) { + DSSERR("can't ioremap DSS\n"); + r = -ENOMEM; + goto fail0; } - dss.dss_clk = clk; + /* disable LCD and DIGIT output. This seems to fix the synclost + * problem that we get, if the bootloader starts the DSS and + * the kernel resets it */ + omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); + +#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET + /* We need to wait here a bit, otherwise we sometimes start to + * get synclost errors, and after that only power cycle will + * restore DSS functionality. I have no idea why this happens. + * And we have to wait _before_ resetting the DSS, but after + * enabling clocks. + * + * This bug was at least present on OMAP3430. It's unknown + * if it happens on OMAP2 or OMAP3630. + */ + msleep(50); +#endif + _omap_dss_reset(); + + /* autoidle */ + REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); + + /* Select DPLL */ + REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); + +#ifdef CONFIG_OMAP2_DSS_VENC + REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ + REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ + REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ +#endif if (cpu_is_omap34xx()) { - clk = clk_get(NULL, "dpll4_m4_ck"); - if (IS_ERR(clk)) { + dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); + if (IS_ERR(dpll4_m4_ck)) { DSSERR("Failed to get dpll4_m4_ck\n"); - r = PTR_ERR(clk); - goto err; + r = PTR_ERR(dpll4_m4_ck); + goto fail1; } } else if (cpu_is_omap44xx()) { - clk = clk_get(NULL, "dpll_per_m5x2_ck"); - if (IS_ERR(clk)) { - DSSERR("Failed to get dpll_per_m5x2_ck\n"); - r = PTR_ERR(clk); - goto err; + dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); + if (IS_ERR(dpll4_m4_ck)) { + DSSERR("Failed to get dpll4_m4_ck\n"); + r = PTR_ERR(dpll4_m4_ck); + goto fail1; } } else { /* omap24xx */ - clk = NULL; + dpll4_m4_ck = NULL; } - dss.dpll4_m4_ck = clk; + dss.dpll4_m4_ck = dpll4_m4_ck; - return 0; + dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; + dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; + dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; + dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; + dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; -err: - if (dss.dss_clk) - clk_put(dss.dss_clk); - if (dss.dpll4_m4_ck) - clk_put(dss.dpll4_m4_ck); + dss_save_context(); + + rev = dss_read_reg(DSS_REVISION); + printk(KERN_INFO "OMAP DSS rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + return 0; +fail1: + iounmap(dss.base); +fail0: return r; } -static void dss_put_clocks(void) +static void dss_exit(void) { if (dss.dpll4_m4_ck) clk_put(dss.dpll4_m4_ck); - clk_put(dss.dss_clk); + + iounmap(dss.base); } -int dss_runtime_get(void) +/* CONTEXT */ +static int dss_get_ctx_id(void) { + struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; int r; - DSSDBG("dss_runtime_get\n"); + if (!pdata->board_data->get_last_off_on_transaction_id) + return 0; + r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); + if (r < 0) { + dev_err(&dss.pdev->dev, "getting transaction ID failed, " + "will force context restore\n"); + r = -1; + } + return r; +} + +int dss_need_ctx_restore(void) +{ + int id = dss_get_ctx_id(); + + if (id < 0 || id != dss.ctx_id) { + DSSDBG("ctx id %d -> id %d\n", + dss.ctx_id, id); + dss.ctx_id = id; + return 1; + } else { + return 0; + } +} + +static void save_all_ctx(void) +{ + DSSDBG("save context\n"); + + dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); + + dss_save_context(); + dispc_save_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_save_context(); +#endif + + dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); +} + +static void restore_all_ctx(void) +{ + DSSDBG("restore context\n"); + + dss_clk_enable_all_no_ctx(); - r = pm_runtime_get_sync(&dss.pdev->dev); - WARN_ON(r < 0); - return r < 0 ? r : 0; + dss_restore_context(); + dispc_restore_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_restore_context(); +#endif + + dss_clk_disable_all_no_ctx(); } -void dss_runtime_put(void) +static int dss_get_clock(struct clk **clock, const char *clk_name) +{ + struct clk *clk; + + clk = clk_get(&dss.pdev->dev, clk_name); + + if (IS_ERR(clk)) { + DSSERR("can't get clock %s", clk_name); + return PTR_ERR(clk); + } + + *clock = clk; + + DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); + + return 0; +} + +static int dss_get_clocks(void) { int r; + struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; + + dss.dss_ick = NULL; + dss.dss_fck = NULL; + dss.dss_sys_clk = NULL; + dss.dss_tv_fck = NULL; + dss.dss_video_fck = NULL; + + r = dss_get_clock(&dss.dss_ick, "ick"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss_fck, "fck"); + if (r) + goto err; + + if (!pdata->opt_clock_available) { + r = -ENODEV; + goto err; + } + + if (pdata->opt_clock_available("sys_clk")) { + r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); + if (r) + goto err; + } + + if (pdata->opt_clock_available("tv_clk")) { + r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); + if (r) + goto err; + } + + if (pdata->opt_clock_available("video_clk")) { + r = dss_get_clock(&dss.dss_video_fck, "video_clk"); + if (r) + goto err; + } + + return 0; + +err: + if (dss.dss_ick) + clk_put(dss.dss_ick); + if (dss.dss_fck) + clk_put(dss.dss_fck); + if (dss.dss_sys_clk) + clk_put(dss.dss_sys_clk); + if (dss.dss_tv_fck) + clk_put(dss.dss_tv_fck); + if (dss.dss_video_fck) + clk_put(dss.dss_video_fck); - DSSDBG("dss_runtime_put\n"); + return r; +} - r = pm_runtime_put(&dss.pdev->dev); - WARN_ON(r < 0); +static void dss_put_clocks(void) +{ + if (dss.dss_video_fck) + clk_put(dss.dss_video_fck); + if (dss.dss_tv_fck) + clk_put(dss.dss_tv_fck); + if (dss.dss_sys_clk) + clk_put(dss.dss_sys_clk); + clk_put(dss.dss_fck); + clk_put(dss.dss_ick); +} + +unsigned long dss_clk_get_rate(enum dss_clock clk) +{ + switch (clk) { + case DSS_CLK_ICK: + return clk_get_rate(dss.dss_ick); + case DSS_CLK_FCK: + return clk_get_rate(dss.dss_fck); + case DSS_CLK_SYSCK: + return clk_get_rate(dss.dss_sys_clk); + case DSS_CLK_TVFCK: + return clk_get_rate(dss.dss_tv_fck); + case DSS_CLK_VIDFCK: + return clk_get_rate(dss.dss_video_fck); + } + + BUG(); + return 0; } +static unsigned count_clk_bits(enum dss_clock clks) +{ + unsigned num_clks = 0; + + if (clks & DSS_CLK_ICK) + ++num_clks; + if (clks & DSS_CLK_FCK) + ++num_clks; + if (clks & DSS_CLK_SYSCK) + ++num_clks; + if (clks & DSS_CLK_TVFCK) + ++num_clks; + if (clks & DSS_CLK_VIDFCK) + ++num_clks; + + return num_clks; +} + +static void dss_clk_enable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_enable(dss.dss_ick); + if (clks & DSS_CLK_FCK) + clk_enable(dss.dss_fck); + if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) + clk_enable(dss.dss_sys_clk); + if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) + clk_enable(dss.dss_tv_fck); + if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) + clk_enable(dss.dss_video_fck); + + dss.num_clks_enabled += num_clks; +} + +void dss_clk_enable(enum dss_clock clks) +{ + bool check_ctx = dss.num_clks_enabled == 0; + + dss_clk_enable_no_ctx(clks); + + /* + * HACK: On omap4 the registers may not be accessible right after + * enabling the clocks. At some point this will be handled by + * pm_runtime, but for the time begin this should make things work. + */ + if (cpu_is_omap44xx() && check_ctx) + udelay(10); + + if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) + restore_all_ctx(); +} + +static void dss_clk_disable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_disable(dss.dss_ick); + if (clks & DSS_CLK_FCK) + clk_disable(dss.dss_fck); + if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) + clk_disable(dss.dss_sys_clk); + if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) + clk_disable(dss.dss_tv_fck); + if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) + clk_disable(dss.dss_video_fck); + + dss.num_clks_enabled -= num_clks; +} + +void dss_clk_disable(enum dss_clock clks) +{ + if (cpu_is_omap34xx()) { + unsigned num_clks = count_clk_bits(clks); + + BUG_ON(dss.num_clks_enabled < num_clks); + + if (dss.num_clks_enabled == num_clks) + save_all_ctx(); + } + + dss_clk_disable_no_ctx(clks); +} + +static void dss_clk_enable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_VIDFCK; + dss_clk_enable_no_ctx(clks); +} + +static void dss_clk_disable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_VIDFCK; + dss_clk_disable_no_ctx(clks); +} + +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +/* CLOCKS */ +static void core_dump_clocks(struct seq_file *s) +{ + int i; + struct clk *clocks[5] = { + dss.dss_ick, + dss.dss_fck, + dss.dss_sys_clk, + dss.dss_tv_fck, + dss.dss_video_fck + }; + + const char *names[5] = { + "ick", + "fck", + "sys_clk", + "tv_fck", + "video_fck" + }; + + seq_printf(s, "- CORE -\n"); + + seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); + + for (i = 0; i < 5; i++) { + if (!clocks[i]) + continue; + seq_printf(s, "%s (%s)%*s\t%lu\t%d\n", + names[i], + clocks[i]->name, + 24 - strlen(names[i]) - strlen(clocks[i]->name), + "", + clk_get_rate(clocks[i]), + clocks[i]->usecount); + } +} +#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ + /* DEBUGFS */ #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) void dss_debug_dump_clocks(struct seq_file *s) { + core_dump_clocks(s); dss_dump_clocks(s); dispc_dump_clocks(s); #ifdef CONFIG_OMAP2_DSS_DSI @@ -724,51 +1089,28 @@ void dss_debug_dump_clocks(struct seq_file *s) } #endif + /* DSS HW IP initialisation */ static int omap_dsshw_probe(struct platform_device *pdev) { - struct resource *dss_mem; - u32 rev; int r; dss.pdev = pdev; - dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); - if (!dss_mem) { - DSSERR("can't get IORESOURCE_MEM DSS\n"); - r = -EINVAL; - goto err_ioremap; - } - dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); - if (!dss.base) { - DSSERR("can't ioremap DSS\n"); - r = -ENOMEM; - goto err_ioremap; - } - r = dss_get_clocks(); if (r) goto err_clocks; - pm_runtime_enable(&pdev->dev); - - r = dss_runtime_get(); - if (r) - goto err_runtime_get; + dss_clk_enable_all_no_ctx(); - /* Select DPLL */ - REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); + dss.ctx_id = dss_get_ctx_id(); + DSSDBG("initial ctx id %u\n", dss.ctx_id); -#ifdef CONFIG_OMAP2_DSS_VENC - REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ - REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ - REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ -#endif - dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; - dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; - dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; - dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; - dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; + r = dss_init(); + if (r) { + DSSERR("Failed to initialize DSS\n"); + goto err_dss; + } r = dpi_init(); if (r) { @@ -782,66 +1124,42 @@ static int omap_dsshw_probe(struct platform_device *pdev) goto err_sdi; } - rev = dss_read_reg(DSS_REVISION); - printk(KERN_INFO "OMAP DSS rev %d.%d\n", - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - - dss_runtime_put(); - + dss_clk_disable_all_no_ctx(); return 0; err_sdi: dpi_exit(); err_dpi: - dss_runtime_put(); -err_runtime_get: - pm_runtime_disable(&pdev->dev); + dss_exit(); +err_dss: + dss_clk_disable_all_no_ctx(); dss_put_clocks(); err_clocks: - iounmap(dss.base); -err_ioremap: return r; } static int omap_dsshw_remove(struct platform_device *pdev) { - dpi_exit(); - sdi_exit(); - iounmap(dss.base); + dss_exit(); - pm_runtime_disable(&pdev->dev); + /* + * As part of hwmod changes, DSS is not the only controller of dss + * clocks; hwmod framework itself will also enable clocks during hwmod + * init for dss, and autoidle is set in h/w for DSS. Hence, there's no + * need to disable clocks if their usecounts > 1. + */ + WARN_ON(dss.num_clks_enabled > 0); dss_put_clocks(); - - return 0; -} - -static int dss_runtime_suspend(struct device *dev) -{ - dss_save_context(); - clk_disable(dss.dss_clk); return 0; } -static int dss_runtime_resume(struct device *dev) -{ - clk_enable(dss.dss_clk); - dss_restore_context(); - return 0; -} - -static const struct dev_pm_ops dss_pm_ops = { - .runtime_suspend = dss_runtime_suspend, - .runtime_resume = dss_runtime_resume, -}; - static struct platform_driver omap_dsshw_driver = { .probe = omap_dsshw_probe, .remove = omap_dsshw_remove, .driver = { .name = "omapdss_dss", .owner = THIS_MODULE, - .pm = &dss_pm_ops, }, }; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index ce17a613a30..8ab6d43329b 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -109,6 +109,14 @@ enum omap_parallel_interface_mode { OMAP_DSS_PARALLELMODE_DSI, }; +enum dss_clock { + DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */ + DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */ + DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */ + DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */ + DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ +}; + enum dss_hdmi_venc_clk_source_select { DSS_VENC_TV_CLK = 0, DSS_HDMI_M_PCLK = 1, @@ -212,10 +220,13 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); int dss_init_platform_driver(void); void dss_uninit_platform_driver(void); -int dss_runtime_get(void); -void dss_runtime_put(void); - void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); +void dss_save_context(void); +void dss_restore_context(void); +void dss_clk_enable(enum dss_clock clks); +void dss_clk_disable(enum dss_clock clks); +unsigned long dss_clk_get_rate(enum dss_clock clk); +int dss_need_ctx_restore(void); const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); void dss_dump_clocks(struct seq_file *s); @@ -272,15 +283,15 @@ struct file_operations; int dsi_init_platform_driver(void); void dsi_uninit_platform_driver(void); -int dsi_runtime_get(struct platform_device *dsidev); -void dsi_runtime_put(struct platform_device *dsidev); - void dsi_dump_clocks(struct seq_file *s); void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, const struct file_operations *debug_fops); void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, const struct file_operations *debug_fops); +void dsi_save_context(void); +void dsi_restore_context(void); + int dsi_init_display(struct omap_dss_device *display); void dsi_irq_handler(void); unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); @@ -306,13 +317,6 @@ static inline int dsi_init_platform_driver(void) static inline void dsi_uninit_platform_driver(void) { } -static inline int dsi_runtime_get(struct platform_device *dsidev) -{ - return 0; -} -static inline void dsi_runtime_put(struct platform_device *dsidev) -{ -} static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) { WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); @@ -380,8 +384,8 @@ void dispc_dump_regs(struct seq_file *s); void dispc_irq_handler(void); void dispc_fake_vsync_irq(void); -int dispc_runtime_get(void); -void dispc_runtime_put(void); +void dispc_save_context(void); +void dispc_restore_context(void); void dispc_enable_sidle(void); void dispc_disable_sidle(void); diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index bd420f9650c..1c18888e5df 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -286,9 +286,7 @@ static const struct omap_dss_features omap3430_dss_features = { FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | - FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | - FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V, + FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC, .num_mgrs = 2, .num_ovls = 3, @@ -308,8 +306,7 @@ static const struct omap_dss_features omap3630_dss_features = { FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | - FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | - FEAT_FIR_COEF_V, + FEAT_DSI_PLL_FREQSEL, .num_mgrs = 2, .num_ovls = 3, @@ -330,8 +327,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | - FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | - FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V, + FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2, .num_mgrs = 3, .num_ovls = 3, @@ -352,8 +348,7 @@ static const struct omap_dss_features omap4_dss_features = { FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | - FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | - FEAT_PRELOAD | FEAT_FIR_COEF_V, + FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2, .num_mgrs = 3, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 5be8103a159..07b346f7d91 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -51,10 +51,6 @@ enum dss_feat_id { FEAT_HDMI_CTS_SWMODE = 1 << 19, FEAT_HANDLE_UV_SEPARATE = 1 << 20, FEAT_ATTR2 = 1 << 21, - FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22, - FEAT_CPR = 1 << 23, - FEAT_PRELOAD = 1 << 24, - FEAT_FIR_COEF_V = 1 << 25, }; /* DSS register field id */ diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 1bbf31329c7..b0555f4f0a7 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -29,9 +29,6 @@ #include <linux/mutex.h> #include <linux/delay.h> #include <linux/string.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/clk.h> #include <video/omapdss.h> #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) @@ -54,9 +51,6 @@ static struct { u8 edid_set; bool custom_set; struct hdmi_config cfg; - - struct clk *sys_clk; - struct clk *hdmi_clk; } hdmi; /* @@ -168,27 +162,6 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, return val; } -static int hdmi_runtime_get(void) -{ - int r; - - DSSDBG("hdmi_runtime_get\n"); - - r = pm_runtime_get_sync(&hdmi.pdev->dev); - WARN_ON(r < 0); - return r < 0 ? r : 0; -} - -static void hdmi_runtime_put(void) -{ - int r; - - DSSDBG("hdmi_runtime_put\n"); - - r = pm_runtime_put(&hdmi.pdev->dev); - WARN_ON(r < 0); -} - int hdmi_init_display(struct omap_dss_device *dssdev) { DSSDBG("init_display\n"); @@ -338,11 +311,30 @@ static int hdmi_phy_init(void) return 0; } +static int hdmi_wait_softreset(void) +{ + /* reset W1 */ + REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0); + + /* wait till SOFTRESET == 0 */ + if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) { + DSSERR("sysconfig reset failed\n"); + return -ETIMEDOUT; + } + + return 0; +} + static int hdmi_pll_program(struct hdmi_pll_info *fmt) { u16 r = 0; enum hdmi_clk_refsel refsel; + /* wait for wrapper reset */ + r = hdmi_wait_softreset(); + if (r) + return r; + r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); if (r) return r; @@ -1072,7 +1064,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, unsigned long clkin, refclk; u32 mf; - clkin = clk_get_rate(hdmi.sys_clk) / 10000; + clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000; /* * Input clock is predivided by N + 1 * out put of which is reference clk @@ -1106,6 +1098,16 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); } +static void hdmi_enable_clocks(int enable) +{ + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | + DSS_CLK_SYSCK | DSS_CLK_VIDFCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | + DSS_CLK_SYSCK | DSS_CLK_VIDFCK); +} + static int hdmi_power_on(struct omap_dss_device *dssdev) { int r, code = 0; @@ -1113,9 +1115,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) struct omap_video_timings *p; unsigned long phy; - r = hdmi_runtime_get(); - if (r) - return r; + hdmi_enable_clocks(1); dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); @@ -1180,7 +1180,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) return 0; err: - hdmi_runtime_put(); + hdmi_enable_clocks(0); return -EIO; } @@ -1191,7 +1191,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev) hdmi_wp_video_start(0); hdmi_phy_off(); hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); - hdmi_runtime_put(); + hdmi_enable_clocks(0); hdmi.edid_set = 0; } @@ -1686,43 +1686,14 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = { }; #endif -static int hdmi_get_clocks(struct platform_device *pdev) -{ - struct clk *clk; - - clk = clk_get(&pdev->dev, "sys_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get sys_clk\n"); - return PTR_ERR(clk); - } - - hdmi.sys_clk = clk; - - clk = clk_get(&pdev->dev, "hdmi_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get hdmi_clk\n"); - clk_put(hdmi.sys_clk); - return PTR_ERR(clk); - } - - hdmi.hdmi_clk = clk; - - return 0; -} - -static void hdmi_put_clocks(void) -{ - if (hdmi.sys_clk) - clk_put(hdmi.sys_clk); - if (hdmi.hdmi_clk) - clk_put(hdmi.hdmi_clk); -} - /* HDMI HW IP initialisation */ static int omapdss_hdmihw_probe(struct platform_device *pdev) { struct resource *hdmi_mem; - int r; +#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ + defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) + int ret; +#endif hdmi.pdata = pdev->dev.platform_data; hdmi.pdev = pdev; @@ -1742,25 +1713,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) return -ENOMEM; } - r = hdmi_get_clocks(pdev); - if (r) { - iounmap(hdmi.base_wp); - return r; - } - - pm_runtime_enable(&pdev->dev); - hdmi_panel_init(); #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) /* Register ASoC codec DAI */ - r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv, + ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv, &hdmi_codec_dai_drv, 1); - if (r) { + if (ret) { DSSERR("can't register ASoC HDMI audio codec\n"); - return r; + return ret; } #endif return 0; @@ -1775,62 +1738,17 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev) snd_soc_unregister_codec(&pdev->dev); #endif - pm_runtime_disable(&pdev->dev); - - hdmi_put_clocks(); - iounmap(hdmi.base_wp); return 0; } -static int hdmi_runtime_suspend(struct device *dev) -{ - clk_disable(hdmi.hdmi_clk); - clk_disable(hdmi.sys_clk); - - dispc_runtime_put(); - dss_runtime_put(); - - return 0; -} - -static int hdmi_runtime_resume(struct device *dev) -{ - int r; - - r = dss_runtime_get(); - if (r < 0) - goto err_get_dss; - - r = dispc_runtime_get(); - if (r < 0) - goto err_get_dispc; - - - clk_enable(hdmi.sys_clk); - clk_enable(hdmi.hdmi_clk); - - return 0; - -err_get_dispc: - dss_runtime_put(); -err_get_dss: - return r; -} - -static const struct dev_pm_ops hdmi_pm_ops = { - .runtime_suspend = hdmi_runtime_suspend, - .runtime_resume = hdmi_runtime_resume, -}; - static struct platform_driver omapdss_hdmihw_driver = { .probe = omapdss_hdmihw_probe, .remove = omapdss_hdmihw_remove, .driver = { .name = "omapdss_hdmi", .owner = THIS_MODULE, - .pm = &hdmi_pm_ops, }, }; diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index c6d26c6e697..9aeea50e33f 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -416,6 +416,8 @@ struct overlay_cache_data { enum omap_burst_size burst_size; u32 fifo_low; u32 fifo_high; + + bool manual_update; }; struct manager_cache_data { @@ -435,6 +437,7 @@ struct manager_cache_data { bool alpha_enabled; + bool manual_upd_display; bool manual_update; bool do_manual_update; @@ -536,15 +539,24 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return 0; - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) - return 0; - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; } else { - irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? - DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2; + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { + enum omap_dss_update_mode mode; + mode = dssdev->driver->get_update_mode(dssdev); + if (mode != OMAP_DSS_UPDATE_AUTO) + return 0; + + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_FRAMEDONE + : DISPC_IRQ_FRAMEDONE2; + } else { + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_VSYNC + : DISPC_IRQ_VSYNC2; + } } mc = &dss_cache.manager_cache[mgr->id]; @@ -605,15 +617,24 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return 0; - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) - return 0; - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; } else { - irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? - DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2; + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { + enum omap_dss_update_mode mode; + mode = dssdev->driver->get_update_mode(dssdev); + if (mode != OMAP_DSS_UPDATE_AUTO) + return 0; + + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_FRAMEDONE + : DISPC_IRQ_FRAMEDONE2; + } else { + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_VSYNC + : DISPC_IRQ_VSYNC2; + } } oc = &dss_cache.overlay_cache[ovl->id]; @@ -742,7 +763,7 @@ static int configure_overlay(enum omap_plane plane) orig_outw = outw; orig_outh = outh; - if (mc->manual_update && mc->do_manual_update) { + if (c->manual_update && mc->do_manual_update) { unsigned bpp; unsigned scale_x_m = w, scale_x_d = outw; unsigned scale_y_m = h, scale_y_d = outh; @@ -907,7 +928,7 @@ static int configure_dispc(void) if (!oc->dirty) continue; - if (mc->manual_update && !mc->do_manual_update) + if (oc->manual_update && !mc->do_manual_update) continue; if (mgr_busy[oc->channel]) { @@ -955,7 +976,7 @@ static int configure_dispc(void) /* We don't need GO with manual update display. LCD iface will * always be turned off after frame, and new settings will be * taken in to use at next update */ - if (!mc->manual_update) + if (!mc->manual_upd_display) dispc_go(i); } @@ -1215,10 +1236,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); - r = dispc_runtime_get(); - if (r) - return r; - spin_lock_irqsave(&dss_cache.lock, flags); /* Configure overlays */ @@ -1285,6 +1302,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) oc->enabled = true; + oc->manual_update = + dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && + dssdev->driver->get_update_mode(dssdev) != + OMAP_DSS_UPDATE_AUTO; + ++num_planes_enabled; } @@ -1319,8 +1341,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) mc->trans_enabled = mgr->info.trans_enabled; mc->alpha_enabled = mgr->info.alpha_enabled; - mc->manual_update = + mc->manual_upd_display = dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; + + mc->manual_update = + dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && + dssdev->driver->get_update_mode(dssdev) != + OMAP_DSS_UPDATE_AUTO; } /* XXX TODO: Try to get fifomerge working. The problem is that it @@ -1382,6 +1409,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) } r = 0; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); if (!dss_cache.irq_enabled) { u32 mask; @@ -1394,11 +1422,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) dss_cache.irq_enabled = true; } configure_dispc(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); spin_unlock_irqrestore(&dss_cache.lock, flags); - dispc_runtime_put(); - return r; } diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index c84380c53c3..0f08025b1f0 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -84,42 +84,32 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, old_mgr = ovl->manager; - r = dispc_runtime_get(); - if (r) - return r; - /* detach old manager */ if (old_mgr) { r = ovl->unset_manager(ovl); if (r) { DSSERR("detach failed\n"); - goto err; + return r; } r = old_mgr->apply(old_mgr); if (r) - goto err; + return r; } if (mgr) { r = ovl->set_manager(ovl, mgr); if (r) { DSSERR("Failed to attach overlay\n"); - goto err; + return r; } r = mgr->apply(mgr); if (r) - goto err; + return r; } - dispc_runtime_put(); - return size; - -err: - dispc_runtime_put(); - return r; } static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) @@ -248,9 +238,6 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, u8 alpha; struct omap_overlay_info info; - if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) - return -ENODEV; - r = kstrtou8(buf, 0, &alpha); if (r) return r; @@ -517,6 +504,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, ovl->manager = mgr; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); /* XXX: When there is an overlay on a DSI manual update display, and * the overlay is first disabled, then moved to tv, and enabled, we * seem to get SYNC_LOST_DIGIT error. @@ -530,6 +518,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, * the overlay, but before moving the overlay to TV. */ dispc_set_channel_out(ovl->id, mgr->id); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; } @@ -730,8 +719,6 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) } if (mgr) { - dispc_runtime_get(); - for (i = 0; i < dss_feat_get_num_ovls(); i++) { struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); @@ -741,8 +728,6 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) omap_dss_set_manager(ovl, mgr); } } - - dispc_runtime_put(); } } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index c57e3fbf239..c06fbe0bc67 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -33,8 +33,6 @@ #include <linux/hrtimer.h> #include <linux/seq_file.h> #include <linux/semaphore.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> #include <video/omapdss.h> #include "dss.h" @@ -122,25 +120,12 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx) return __raw_readl(rfbi.base + idx.idx); } -static int rfbi_runtime_get(void) +static void rfbi_enable_clocks(bool enable) { - int r; - - DSSDBG("rfbi_runtime_get\n"); - - r = pm_runtime_get_sync(&rfbi.pdev->dev); - WARN_ON(r < 0); - return r < 0 ? r : 0; -} - -static void rfbi_runtime_put(void) -{ - int r; - - DSSDBG("rfbi_runtime_put\n"); - - r = pm_runtime_put(&rfbi.pdev->dev); - WARN_ON(r < 0); + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } void rfbi_bus_lock(void) @@ -820,8 +805,7 @@ void rfbi_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) - if (rfbi_runtime_get()) - return; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(RFBI_REVISION); DUMPREG(RFBI_SYSCONFIG); @@ -852,7 +836,7 @@ void rfbi_dump_regs(struct seq_file *s) DUMPREG(RFBI_VSYNC_WIDTH); DUMPREG(RFBI_HSYNC_WIDTH); - rfbi_runtime_put(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -860,9 +844,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { int r; - r = rfbi_runtime_get(); - if (r) - return r; + rfbi_enable_clocks(1); r = omap_dss_start_device(dssdev); if (r) { @@ -897,7 +879,6 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) err1: omap_dss_stop_device(dssdev); err0: - rfbi_runtime_put(); return r; } EXPORT_SYMBOL(omapdss_rfbi_display_enable); @@ -908,7 +889,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) DISPC_IRQ_FRAMEDONE); omap_dss_stop_device(dssdev); - rfbi_runtime_put(); + rfbi_enable_clocks(0); } EXPORT_SYMBOL(omapdss_rfbi_display_disable); @@ -923,9 +904,8 @@ int rfbi_init_display(struct omap_dss_device *dssdev) static int omap_rfbihw_probe(struct platform_device *pdev) { u32 rev; + u32 l; struct resource *rfbi_mem; - struct clk *clk; - int r; rfbi.pdev = pdev; @@ -934,99 +914,46 @@ static int omap_rfbihw_probe(struct platform_device *pdev) rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); if (!rfbi_mem) { DSSERR("can't get IORESOURCE_MEM RFBI\n"); - r = -EINVAL; - goto err_ioremap; + return -EINVAL; } rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); if (!rfbi.base) { DSSERR("can't ioremap RFBI\n"); - r = -ENOMEM; - goto err_ioremap; + return -ENOMEM; } - pm_runtime_enable(&pdev->dev); - - r = rfbi_runtime_get(); - if (r) - goto err_get_rfbi; + rfbi_enable_clocks(1); msleep(10); - clk = clk_get(&pdev->dev, "rfbi_iclk"); - if (IS_ERR(clk)) { - DSSERR("can't get rfbi_iclk\n"); - r = PTR_ERR(clk); - goto err_get_ick; - } - - rfbi.l4_khz = clk_get_rate(clk) / 1000; + rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; - clk_put(clk); + /* Enable autoidle and smart-idle */ + l = rfbi_read_reg(RFBI_SYSCONFIG); + l |= (1 << 0) | (2 << 3); + rfbi_write_reg(RFBI_SYSCONFIG, l); rev = rfbi_read_reg(RFBI_REVISION); dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - rfbi_runtime_put(); + rfbi_enable_clocks(0); return 0; - -err_get_ick: - rfbi_runtime_put(); -err_get_rfbi: - pm_runtime_disable(&pdev->dev); - iounmap(rfbi.base); -err_ioremap: - return r; } static int omap_rfbihw_remove(struct platform_device *pdev) { - pm_runtime_disable(&pdev->dev); iounmap(rfbi.base); return 0; } -static int rfbi_runtime_suspend(struct device *dev) -{ - dispc_runtime_put(); - dss_runtime_put(); - - return 0; -} - -static int rfbi_runtime_resume(struct device *dev) -{ - int r; - - r = dss_runtime_get(); - if (r < 0) - goto err_get_dss; - - r = dispc_runtime_get(); - if (r < 0) - goto err_get_dispc; - - return 0; - -err_get_dispc: - dss_runtime_put(); -err_get_dss: - return r; -} - -static const struct dev_pm_ops rfbi_pm_ops = { - .runtime_suspend = rfbi_runtime_suspend, - .runtime_resume = rfbi_runtime_resume, -}; - static struct platform_driver omap_rfbihw_driver = { .probe = omap_rfbihw_probe, .remove = omap_rfbihw_remove, .driver = { .name = "omapdss_rfbi", .owner = THIS_MODULE, - .pm = &rfbi_pm_ops, }, }; diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 3a688c871a4..0bd4b0350f8 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -20,11 +20,13 @@ #define DSS_SUBSYS_NAME "SDI" #include <linux/kernel.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/regulator/consumer.h> #include <video/omapdss.h> +#include <plat/cpu.h> #include "dss.h" static struct { @@ -58,20 +60,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); - goto err_start_dev; + goto err0; } r = regulator_enable(sdi.vdds_sdi_reg); if (r) - goto err_reg_enable; + goto err1; - r = dss_runtime_get(); - if (r) - goto err_get_dss; - - r = dispc_runtime_get(); - if (r) - goto err_get_dispc; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); sdi_basic_init(dssdev); @@ -84,7 +80,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) r = dss_calc_clock_div(1, t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); if (r) - goto err_calc_clock_div; + goto err2; fck = dss_cinfo.fck; lck_div = dispc_cinfo.lck_div; @@ -105,34 +101,27 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) r = dss_set_clock_div(&dss_cinfo); if (r) - goto err_set_dss_clock_div; + goto err2; r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); if (r) - goto err_set_dispc_clock_div; + goto err2; dss_sdi_init(dssdev->phy.sdi.datapairs); r = dss_sdi_enable(); if (r) - goto err_sdi_enable; + goto err1; mdelay(2); dssdev->manager->enable(dssdev->manager); return 0; - -err_sdi_enable: -err_set_dispc_clock_div: -err_set_dss_clock_div: -err_calc_clock_div: - dispc_runtime_put(); -err_get_dispc: - dss_runtime_put(); -err_get_dss: +err2: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); regulator_disable(sdi.vdds_sdi_reg); -err_reg_enable: +err1: omap_dss_stop_device(dssdev); -err_start_dev: +err0: return r; } EXPORT_SYMBOL(omapdss_sdi_display_enable); @@ -143,8 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) dss_sdi_disable(); - dispc_runtime_put(); - dss_runtime_put(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); regulator_disable(sdi.vdds_sdi_reg); diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index f75159dc7f7..980f919ed98 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -33,13 +33,11 @@ #include <linux/seq_file.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> -#include <linux/pm_runtime.h> #include <video/omapdss.h> #include <plat/cpu.h> #include "dss.h" -#include "dss_features.h" /* Venc registers */ #define VENC_REV_ID 0x00 @@ -294,9 +292,6 @@ static struct { struct mutex venc_lock; u32 wss_data; struct regulator *vdda_dac_reg; - - struct clk *tv_clk; - struct clk *tv_dac_clk; } venc; static inline void venc_write_reg(int idx, u32 val) @@ -385,25 +380,14 @@ static void venc_reset(void) #endif } -static int venc_runtime_get(void) -{ - int r; - - DSSDBG("venc_runtime_get\n"); - - r = pm_runtime_get_sync(&venc.pdev->dev); - WARN_ON(r < 0); - return r < 0 ? r : 0; -} - -static void venc_runtime_put(void) +static void venc_enable_clocks(int enable) { - int r; - - DSSDBG("venc_runtime_put\n"); - - r = pm_runtime_put(&venc.pdev->dev); - WARN_ON(r < 0); + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | + DSS_CLK_VIDFCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | + DSS_CLK_VIDFCK); } static const struct venc_config *venc_timings_to_config( @@ -422,6 +406,8 @@ static void venc_power_on(struct omap_dss_device *dssdev) { u32 l; + venc_enable_clocks(1); + venc_reset(); venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); @@ -462,6 +448,8 @@ static void venc_power_off(struct omap_dss_device *dssdev) dssdev->platform_disable(dssdev); regulator_disable(venc.vdda_dac_reg); + + venc_enable_clocks(0); } @@ -499,10 +487,6 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) goto err1; } - r = venc_runtime_get(); - if (r) - goto err1; - venc_power_on(dssdev); venc.wss_data = 0; @@ -536,8 +520,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev) venc_power_off(dssdev); - venc_runtime_put(); - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; omap_dss_stop_device(dssdev); @@ -556,6 +538,20 @@ static int venc_panel_resume(struct omap_dss_device *dssdev) return venc_panel_enable(dssdev); } +static enum omap_dss_update_mode venc_get_update_mode( + struct omap_dss_device *dssdev) +{ + return OMAP_DSS_UPDATE_AUTO; +} + +static int venc_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + if (mode != OMAP_DSS_UPDATE_AUTO) + return -EINVAL; + return 0; +} + static void venc_get_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { @@ -602,7 +598,6 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev) static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) { const struct venc_config *config; - int r; DSSDBG("venc_set_wss\n"); @@ -613,19 +608,16 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) /* Invert due to VENC_L21_WC_CTL:INV=1 */ venc.wss_data = (wss ^ 0xfffff) << 8; - r = venc_runtime_get(); - if (r) - goto err; + venc_enable_clocks(1); venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | venc.wss_data); - venc_runtime_put(); + venc_enable_clocks(0); -err: mutex_unlock(&venc.venc_lock); - return r; + return 0; } static struct omap_dss_driver venc_driver = { @@ -640,6 +632,9 @@ static struct omap_dss_driver venc_driver = { .get_resolution = omapdss_default_get_resolution, .get_recommended_bpp = omapdss_default_get_recommended_bpp, + .set_update_mode = venc_set_update_mode, + .get_update_mode = venc_get_update_mode, + .get_timings = venc_get_timings, .set_timings = venc_set_timings, .check_timings = venc_check_timings, @@ -678,8 +673,7 @@ void venc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) - if (venc_runtime_get()) - return; + venc_enable_clocks(1); DUMPREG(VENC_F_CONTROL); DUMPREG(VENC_VIDOUT_CTRL); @@ -723,53 +717,16 @@ void venc_dump_regs(struct seq_file *s) DUMPREG(VENC_OUTPUT_CONTROL); DUMPREG(VENC_OUTPUT_TEST); - venc_runtime_put(); + venc_enable_clocks(0); #undef DUMPREG } -static int venc_get_clocks(struct platform_device *pdev) -{ - struct clk *clk; - - clk = clk_get(&pdev->dev, "tv_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get tv_clk\n"); - return PTR_ERR(clk); - } - - venc.tv_clk = clk; - - if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { - clk = clk_get(&pdev->dev, "tv_dac_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get tv_dac_clk\n"); - clk_put(venc.tv_clk); - return PTR_ERR(clk); - } - } else { - clk = NULL; - } - - venc.tv_dac_clk = clk; - - return 0; -} - -static void venc_put_clocks(void) -{ - if (venc.tv_clk) - clk_put(venc.tv_clk); - if (venc.tv_dac_clk) - clk_put(venc.tv_dac_clk); -} - /* VENC HW IP initialisation */ static int omap_venchw_probe(struct platform_device *pdev) { u8 rev_id; struct resource *venc_mem; - int r; venc.pdev = pdev; @@ -780,40 +737,22 @@ static int omap_venchw_probe(struct platform_device *pdev) venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); if (!venc_mem) { DSSERR("can't get IORESOURCE_MEM VENC\n"); - r = -EINVAL; - goto err_ioremap; + return -EINVAL; } venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); if (!venc.base) { DSSERR("can't ioremap VENC\n"); - r = -ENOMEM; - goto err_ioremap; + return -ENOMEM; } - r = venc_get_clocks(pdev); - if (r) - goto err_get_clk; - - pm_runtime_enable(&pdev->dev); - - r = venc_runtime_get(); - if (r) - goto err_get_venc; + venc_enable_clocks(1); rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); - venc_runtime_put(); + venc_enable_clocks(0); return omap_dss_register_driver(&venc_driver); - -err_get_venc: - pm_runtime_disable(&pdev->dev); - venc_put_clocks(); -err_get_clk: - iounmap(venc.base); -err_ioremap: - return r; } static int omap_venchw_remove(struct platform_device *pdev) @@ -824,61 +763,16 @@ static int omap_venchw_remove(struct platform_device *pdev) } omap_dss_unregister_driver(&venc_driver); - pm_runtime_disable(&pdev->dev); - venc_put_clocks(); - iounmap(venc.base); return 0; } -static int venc_runtime_suspend(struct device *dev) -{ - if (venc.tv_dac_clk) - clk_disable(venc.tv_dac_clk); - clk_disable(venc.tv_clk); - - dispc_runtime_put(); - dss_runtime_put(); - - return 0; -} - -static int venc_runtime_resume(struct device *dev) -{ - int r; - - r = dss_runtime_get(); - if (r < 0) - goto err_get_dss; - - r = dispc_runtime_get(); - if (r < 0) - goto err_get_dispc; - - clk_enable(venc.tv_clk); - if (venc.tv_dac_clk) - clk_enable(venc.tv_dac_clk); - - return 0; - -err_get_dispc: - dss_runtime_put(); -err_get_dss: - return r; -} - -static const struct dev_pm_ops venc_pm_ops = { - .runtime_suspend = venc_runtime_suspend, - .runtime_resume = venc_runtime_resume, -}; - static struct platform_driver omap_venchw_driver = { .probe = omap_venchw_probe, .remove = omap_venchw_remove, .driver = { .name = "omapdss_venc", .owner = THIS_MODULE, - .pm = &venc_pm_ops, }, }; diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 6b1ac23dbbd..cff450392b7 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -316,67 +316,67 @@ int omapfb_update_window(struct fb_info *fbi, } EXPORT_SYMBOL(omapfb_update_window); -int omapfb_set_update_mode(struct fb_info *fbi, +static int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode) { struct omap_dss_device *display = fb2display(fbi); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omapfb_display_data *d; + enum omap_dss_update_mode um; int r; - if (!display) - return -EINVAL; - - if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE) + if (!display || !display->driver->set_update_mode) return -EINVAL; - omapfb_lock(fbdev); - - d = get_display_data(fbdev, display); - - if (d->update_mode == mode) { - omapfb_unlock(fbdev); - return 0; - } + switch (mode) { + case OMAPFB_UPDATE_DISABLED: + um = OMAP_DSS_UPDATE_DISABLED; + break; - r = 0; + case OMAPFB_AUTO_UPDATE: + um = OMAP_DSS_UPDATE_AUTO; + break; - if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { - if (mode == OMAPFB_AUTO_UPDATE) - omapfb_start_auto_update(fbdev, display); - else /* MANUAL_UPDATE */ - omapfb_stop_auto_update(fbdev, display); + case OMAPFB_MANUAL_UPDATE: + um = OMAP_DSS_UPDATE_MANUAL; + break; - d->update_mode = mode; - } else { /* AUTO_UPDATE */ - if (mode == OMAPFB_MANUAL_UPDATE) - r = -EINVAL; + default: + return -EINVAL; } - omapfb_unlock(fbdev); + r = display->driver->set_update_mode(display, um); return r; } -int omapfb_get_update_mode(struct fb_info *fbi, +static int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode) { struct omap_dss_device *display = fb2display(fbi); - struct omapfb_info *ofbi = FB2OFB(fbi); - struct omapfb2_device *fbdev = ofbi->fbdev; - struct omapfb_display_data *d; + enum omap_dss_update_mode m; if (!display) return -EINVAL; - omapfb_lock(fbdev); - - d = get_display_data(fbdev, display); + if (!display->driver->get_update_mode) { + *mode = OMAPFB_AUTO_UPDATE; + return 0; + } - *mode = d->update_mode; + m = display->driver->get_update_mode(display); - omapfb_unlock(fbdev); + switch (m) { + case OMAP_DSS_UPDATE_DISABLED: + *mode = OMAPFB_UPDATE_DISABLED; + break; + case OMAP_DSS_UPDATE_AUTO: + *mode = OMAPFB_AUTO_UPDATE; + break; + case OMAP_DSS_UPDATE_MANUAL: + *mode = OMAPFB_MANUAL_UPDATE; + break; + default: + BUG(); + } return 0; } diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 602b71a92d3..505bc12a303 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -46,10 +46,6 @@ static char *def_vram; static int def_vrfb; static int def_rotate; static int def_mirror; -static bool auto_update; -static unsigned int auto_update_freq; -module_param(auto_update, bool, 0); -module_param(auto_update_freq, uint, 0644); #ifdef DEBUG unsigned int omapfb_debug; @@ -1246,7 +1242,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb2_device *fbdev = ofbi->fbdev; struct omap_dss_device *display = fb2display(fbi); - struct omapfb_display_data *d; int r = 0; if (!display) @@ -1254,8 +1249,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) omapfb_lock(fbdev); - d = get_display_data(fbdev, display); - switch (blank) { case FB_BLANK_UNBLANK: if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) @@ -1264,11 +1257,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) if (display->driver->resume) r = display->driver->resume(display); - if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && - d->update_mode == OMAPFB_AUTO_UPDATE && - !d->auto_update_work_enabled) - omapfb_start_auto_update(fbdev, display); - break; case FB_BLANK_NORMAL: @@ -1280,9 +1268,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) if (display->state != OMAP_DSS_DISPLAY_ACTIVE) goto exit; - if (d->auto_update_work_enabled) - omapfb_stop_auto_update(fbdev, display); - if (display->driver->suspend) r = display->driver->suspend(display); @@ -1739,78 +1724,6 @@ err: return r; } -static void omapfb_auto_update_work(struct work_struct *work) -{ - struct omap_dss_device *dssdev; - struct omap_dss_driver *dssdrv; - struct omapfb_display_data *d; - u16 w, h; - unsigned int freq; - struct omapfb2_device *fbdev; - - d = container_of(work, struct omapfb_display_data, - auto_update_work.work); - - dssdev = d->dssdev; - dssdrv = dssdev->driver; - fbdev = d->fbdev; - - if (!dssdrv || !dssdrv->update) - return; - - if (dssdrv->sync) - dssdrv->sync(dssdev); - - dssdrv->get_resolution(dssdev, &w, &h); - dssdrv->update(dssdev, 0, 0, w, h); - - freq = auto_update_freq; - if (freq == 0) - freq = 20; - queue_delayed_work(fbdev->auto_update_wq, - &d->auto_update_work, HZ / freq); -} - -void omapfb_start_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display) -{ - struct omapfb_display_data *d; - - if (fbdev->auto_update_wq == NULL) { - struct workqueue_struct *wq; - - wq = create_singlethread_workqueue("omapfb_auto_update"); - - if (wq == NULL) { - dev_err(fbdev->dev, "Failed to create workqueue for " - "auto-update\n"); - return; - } - - fbdev->auto_update_wq = wq; - } - - d = get_display_data(fbdev, display); - - INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work); - - d->auto_update_work_enabled = true; - - omapfb_auto_update_work(&d->auto_update_work.work); -} - -void omapfb_stop_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display) -{ - struct omapfb_display_data *d; - - d = get_display_data(fbdev, display); - - cancel_delayed_work_sync(&d->auto_update_work); - - d->auto_update_work_enabled = false; -} - /* initialize fb_info, var, fix to something sane based on the display */ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) { @@ -1945,21 +1858,10 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev) } for (i = 0; i < fbdev->num_displays; i++) { - struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; - - if (fbdev->displays[i].auto_update_work_enabled) - omapfb_stop_auto_update(fbdev, dssdev); - - if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) - dssdev->driver->disable(dssdev); - - omap_dss_put_device(dssdev); - } + if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED) + fbdev->displays[i]->driver->disable(fbdev->displays[i]); - if (fbdev->auto_update_wq != NULL) { - flush_workqueue(fbdev->auto_update_wq); - destroy_workqueue(fbdev->auto_update_wq); - fbdev->auto_update_wq = NULL; + omap_dss_put_device(fbdev->displays[i]); } dev_set_drvdata(fbdev->dev, NULL); @@ -2182,14 +2084,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, int r; u8 bpp; struct omap_video_timings timings, temp_timings; - struct omapfb_display_data *d; r = omapfb_mode_to_timings(mode_str, &timings, &bpp); if (r) return r; - d = get_display_data(fbdev, display); - d->bpp_override = bpp; + fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display; + fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp; + ++fbdev->num_bpp_overrides; if (display->driver->check_timings) { r = display->driver->check_timings(display, &timings); @@ -2215,14 +2117,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev, struct omap_dss_device *dssdev) { - struct omapfb_display_data *d; + int i; BUG_ON(dssdev->driver->get_recommended_bpp == NULL); - d = get_display_data(fbdev, dssdev); - - if (d->bpp_override != 0) - return d->bpp_override; + for (i = 0; i < fbdev->num_bpp_overrides; ++i) { + if (dssdev == fbdev->bpp_overrides[i].dssdev) + return fbdev->bpp_overrides[i].bpp; + } return dssdev->driver->get_recommended_bpp(dssdev); } @@ -2254,9 +2156,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) display = NULL; for (i = 0; i < fbdev->num_displays; ++i) { - if (strcmp(fbdev->displays[i].dssdev->name, + if (strcmp(fbdev->displays[i]->name, display_str) == 0) { - display = fbdev->displays[i].dssdev; + display = fbdev->displays[i]; break; } } @@ -2280,7 +2182,6 @@ static int omapfb_init_display(struct omapfb2_device *fbdev, struct omap_dss_device *dssdev) { struct omap_dss_driver *dssdrv = dssdev->driver; - struct omapfb_display_data *d; int r; r = dssdrv->enable(dssdev); @@ -2290,20 +2191,8 @@ static int omapfb_init_display(struct omapfb2_device *fbdev, return r; } - d = get_display_data(fbdev, dssdev); - - d->fbdev = fbdev; - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { u16 w, h; - - if (auto_update) { - omapfb_start_auto_update(fbdev, dssdev); - d->update_mode = OMAPFB_AUTO_UPDATE; - } else { - d->update_mode = OMAPFB_MANUAL_UPDATE; - } - if (dssdrv->enable_te) { r = dssdrv->enable_te(dssdev, 1); if (r) { @@ -2312,6 +2201,16 @@ static int omapfb_init_display(struct omapfb2_device *fbdev, } } + if (dssdrv->set_update_mode) { + r = dssdrv->set_update_mode(dssdev, + OMAP_DSS_UPDATE_MANUAL); + if (r) { + dev_err(fbdev->dev, + "Failed to set update mode\n"); + return r; + } + } + dssdrv->get_resolution(dssdev, &w, &h); r = dssdrv->update(dssdev, 0, 0, w, h); if (r) { @@ -2320,7 +2219,15 @@ static int omapfb_init_display(struct omapfb2_device *fbdev, return r; } } else { - d->update_mode = OMAPFB_AUTO_UPDATE; + if (dssdrv->set_update_mode) { + r = dssdrv->set_update_mode(dssdev, + OMAP_DSS_UPDATE_AUTO); + if (r) { + dev_err(fbdev->dev, + "Failed to set update mode\n"); + return r; + } + } } return 0; @@ -2368,8 +2275,6 @@ static int omapfb_probe(struct platform_device *pdev) fbdev->num_displays = 0; dssdev = NULL; for_each_dss_dev(dssdev) { - struct omapfb_display_data *d; - omap_dss_get_device(dssdev); if (!dssdev->driver) { @@ -2377,12 +2282,7 @@ static int omapfb_probe(struct platform_device *pdev) r = -ENODEV; } - d = &fbdev->displays[fbdev->num_displays++]; - d->dssdev = dssdev; - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) - d->update_mode = OMAPFB_MANUAL_UPDATE; - else - d->update_mode = OMAPFB_AUTO_UPDATE; + fbdev->displays[fbdev->num_displays++] = dssdev; } if (r) diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 153bf1aceeb..2f5e817b2a9 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c @@ -518,39 +518,6 @@ static ssize_t show_virt(struct device *dev, return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr); } -static ssize_t show_upd_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - enum omapfb_update_mode mode; - int r; - - r = omapfb_get_update_mode(fbi, &mode); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode); -} - -static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - unsigned mode; - int r; - - r = kstrtouint(buf, 0, &mode); - if (r) - return r; - - r = omapfb_set_update_mode(fbi, mode); - if (r) - return r; - - return count; -} - static struct device_attribute omapfb_attrs[] = { __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, store_rotate_type), @@ -561,7 +528,6 @@ static struct device_attribute omapfb_attrs[] = { store_overlays_rotate), __ATTR(phys_addr, S_IRUGO, show_phys, NULL), __ATTR(virt_addr, S_IRUGO, show_virt, NULL), - __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode), }; int omapfb_create_sysfs(struct omapfb2_device *fbdev) diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index fdf0edeccf4..aa1b1d97427 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h @@ -73,15 +73,6 @@ struct omapfb_info { bool mirror; }; -struct omapfb_display_data { - struct omapfb2_device *fbdev; - struct omap_dss_device *dssdev; - u8 bpp_override; - enum omapfb_update_mode update_mode; - bool auto_update_work_enabled; - struct delayed_work auto_update_work; -}; - struct omapfb2_device { struct device *dev; struct mutex mtx; @@ -95,13 +86,17 @@ struct omapfb2_device { struct omapfb2_mem_region regions[10]; unsigned num_displays; - struct omapfb_display_data displays[10]; + struct omap_dss_device *displays[10]; unsigned num_overlays; struct omap_overlay *overlays[10]; unsigned num_managers; struct omap_overlay_manager *managers[10]; - struct workqueue_struct *auto_update_wq; + unsigned num_bpp_overrides; + struct { + struct omap_dss_device *dssdev; + u8 bpp; + } bpp_overrides[10]; }; struct omapfb_colormode { @@ -133,13 +128,6 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode, int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, u16 posx, u16 posy, u16 outw, u16 outh); -void omapfb_start_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display); -void omapfb_stop_auto_update(struct omapfb2_device *fbdev, - struct omap_dss_device *display); -int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode); -int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode); - /* find the display connected to this fb, if any */ static inline struct omap_dss_device *fb2display(struct fb_info *fbi) { @@ -155,19 +143,6 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi) return NULL; } -static inline struct omapfb_display_data *get_display_data( - struct omapfb2_device *fbdev, struct omap_dss_device *dssdev) -{ - int i; - - for (i = 0; i < fbdev->num_displays; ++i) - if (fbdev->displays[i].dssdev == dssdev) - return &fbdev->displays[i]; - - /* This should never happen */ - BUG(); -} - static inline void omapfb_lock(struct omapfb2_device *fbdev) { mutex_lock(&fbdev->mtx); |
