Commit 498f9620 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fbdev-fixes-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux

Pull fbdev fixes from Tomi Valkeinen:
 - fix build errors for bf54x-lq043fb and imxfb
 - fbcon fix for da8xx-fb
 - omapdss fixes for hdmi audio, irq handling and fclk calculation

* tag 'fbdev-fixes-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux:
  video: bf54x-lq043fb: fix build error
  OMAPDSS: Change struct reg_field to dispc_reg_field
  OMAPDSS: Take pixelclock unit change into account in hdmi_compute_acr()
  OMAPDSS: fix shared irq handlers
  video: imxfb: Select LCD_CLASS_DEVICE unconditionally
  OMAPDSS: fix rounding when calculating fclk rate
  video: da8xx-fb: Fix casting of info->pseudo_palette
parents 5f63517c c26ef3eb
...@@ -359,6 +359,8 @@ config FB_SA1100 ...@@ -359,6 +359,8 @@ config FB_SA1100
config FB_IMX config FB_IMX
tristate "Freescale i.MX1/21/25/27 LCD support" tristate "Freescale i.MX1/21/25/27 LCD support"
depends on FB && ARCH_MXC depends on FB && ARCH_MXC
select BACKLIGHT_LCD_SUPPORT
select LCD_CLASS_DEVICE
select FB_CFB_FILLRECT select FB_CFB_FILLRECT
select FB_CFB_COPYAREA select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT select FB_CFB_IMAGEBLIT
......
...@@ -49,13 +49,13 @@ ...@@ -49,13 +49,13 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h>
#include <asm/blackfin.h> #include <asm/blackfin.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/dpmc.h> #include <asm/dpmc.h>
#include <asm/dma-mapping.h> #include <asm/dma-mapping.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/gpio.h>
#include <asm/portmux.h> #include <asm/portmux.h>
#include <mach/bf54x-lq043.h> #include <mach/bf54x-lq043.h>
......
...@@ -663,15 +663,7 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, ...@@ -663,15 +663,7 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
(green << info->var.green.offset) | (green << info->var.green.offset) |
(blue << info->var.blue.offset); (blue << info->var.blue.offset);
switch (info->var.bits_per_pixel) { ((u32 *) (info->pseudo_palette))[regno] = v;
case 16:
((u16 *) (info->pseudo_palette))[regno] = v;
break;
case 24:
case 32:
((u32 *) (info->pseudo_palette))[regno] = v;
break;
}
if (palette[0] != 0x4000) { if (palette[0] != 0x4000) {
update_hw = 1; update_hw = 1;
palette[0] = 0x4000; palette[0] = 0x4000;
......
...@@ -101,6 +101,8 @@ static struct { ...@@ -101,6 +101,8 @@ static struct {
void __iomem *base; void __iomem *base;
int irq; int irq;
irq_handler_t user_handler;
void *user_data;
unsigned long core_clk_rate; unsigned long core_clk_rate;
unsigned long tv_pclk_rate; unsigned long tv_pclk_rate;
...@@ -113,6 +115,8 @@ static struct { ...@@ -113,6 +115,8 @@ static struct {
u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
const struct dispc_features *feat; const struct dispc_features *feat;
bool is_enabled;
} dispc; } dispc;
enum omap_color_component { enum omap_color_component {
...@@ -141,12 +145,18 @@ enum mgr_reg_fields { ...@@ -141,12 +145,18 @@ enum mgr_reg_fields {
DISPC_MGR_FLD_NUM, DISPC_MGR_FLD_NUM,
}; };
struct dispc_reg_field {
u16 reg;
u8 high;
u8 low;
};
static const struct { static const struct {
const char *name; const char *name;
u32 vsync_irq; u32 vsync_irq;
u32 framedone_irq; u32 framedone_irq;
u32 sync_lost_irq; u32 sync_lost_irq;
struct reg_field reg_desc[DISPC_MGR_FLD_NUM]; struct dispc_reg_field reg_desc[DISPC_MGR_FLD_NUM];
} mgr_desc[] = { } mgr_desc[] = {
[OMAP_DSS_CHANNEL_LCD] = { [OMAP_DSS_CHANNEL_LCD] = {
.name = "LCD", .name = "LCD",
...@@ -238,13 +248,13 @@ static inline u32 dispc_read_reg(const u16 idx) ...@@ -238,13 +248,13 @@ static inline u32 dispc_read_reg(const u16 idx)
static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld) static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
{ {
const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld]; const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
return REG_GET(rfld.reg, rfld.high, rfld.low); return REG_GET(rfld.reg, rfld.high, rfld.low);
} }
static void mgr_fld_write(enum omap_channel channel, static void mgr_fld_write(enum omap_channel channel,
enum mgr_reg_fields regfld, int val) { enum mgr_reg_fields regfld, int val) {
const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld]; const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low); REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
} }
...@@ -3669,16 +3679,44 @@ static int __init dispc_init_features(struct platform_device *pdev) ...@@ -3669,16 +3679,44 @@ static int __init dispc_init_features(struct platform_device *pdev)
return 0; return 0;
} }
static irqreturn_t dispc_irq_handler(int irq, void *arg)
{
if (!dispc.is_enabled)
return IRQ_NONE;
return dispc.user_handler(irq, dispc.user_data);
}
int dispc_request_irq(irq_handler_t handler, void *dev_id) int dispc_request_irq(irq_handler_t handler, void *dev_id)
{ {
return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler, int r;
IRQF_SHARED, "OMAP DISPC", dev_id);
if (dispc.user_handler != NULL)
return -EBUSY;
dispc.user_handler = handler;
dispc.user_data = dev_id;
/* ensure the dispc_irq_handler sees the values above */
smp_wmb();
r = devm_request_irq(&dispc.pdev->dev, dispc.irq, dispc_irq_handler,
IRQF_SHARED, "OMAP DISPC", &dispc);
if (r) {
dispc.user_handler = NULL;
dispc.user_data = NULL;
}
return r;
} }
EXPORT_SYMBOL(dispc_request_irq); EXPORT_SYMBOL(dispc_request_irq);
void dispc_free_irq(void *dev_id) void dispc_free_irq(void *dev_id)
{ {
devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id); devm_free_irq(&dispc.pdev->dev, dispc.irq, &dispc);
dispc.user_handler = NULL;
dispc.user_data = NULL;
} }
EXPORT_SYMBOL(dispc_free_irq); EXPORT_SYMBOL(dispc_free_irq);
...@@ -3750,6 +3788,12 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev) ...@@ -3750,6 +3788,12 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
static int dispc_runtime_suspend(struct device *dev) static int dispc_runtime_suspend(struct device *dev)
{ {
dispc.is_enabled = false;
/* ensure the dispc_irq_handler sees the is_enabled value */
smp_wmb();
/* wait for current handler to finish before turning the DISPC off */
synchronize_irq(dispc.irq);
dispc_save_context(); dispc_save_context();
return 0; return 0;
...@@ -3763,12 +3807,15 @@ static int dispc_runtime_resume(struct device *dev) ...@@ -3763,12 +3807,15 @@ static int dispc_runtime_resume(struct device *dev)
* _omap_dispc_initial_config(). We can thus use it to detect if * _omap_dispc_initial_config(). We can thus use it to detect if
* we have lost register context. * we have lost register context.
*/ */
if (REG_GET(DISPC_CONFIG, 2, 1) == OMAP_DSS_LOAD_FRAME_ONLY) if (REG_GET(DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
return 0; _omap_dispc_initial_config();
_omap_dispc_initial_config(); dispc_restore_context();
}
dispc_restore_context(); dispc.is_enabled = true;
/* ensure the dispc_irq_handler sees the is_enabled value */
smp_wmb();
return 0; return 0;
} }
......
...@@ -297,6 +297,8 @@ struct dsi_data { ...@@ -297,6 +297,8 @@ struct dsi_data {
int irq; int irq;
bool is_enabled;
struct clk *dss_clk; struct clk *dss_clk;
struct clk *sys_clk; struct clk *sys_clk;
...@@ -795,6 +797,9 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) ...@@ -795,6 +797,9 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
dsidev = (struct platform_device *) arg; dsidev = (struct platform_device *) arg;
dsi = dsi_get_dsidrv_data(dsidev); dsi = dsi_get_dsidrv_data(dsidev);
if (!dsi->is_enabled)
return IRQ_NONE;
spin_lock(&dsi->irq_lock); spin_lock(&dsi->irq_lock);
irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS); irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS);
...@@ -5671,6 +5676,15 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev) ...@@ -5671,6 +5676,15 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
static int dsi_runtime_suspend(struct device *dev) static int dsi_runtime_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev);
struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
dsi->is_enabled = false;
/* ensure the irq handler sees the is_enabled value */
smp_wmb();
/* wait for current handler to finish before turning the DSI off */
synchronize_irq(dsi->irq);
dispc_runtime_put(); dispc_runtime_put();
return 0; return 0;
...@@ -5678,12 +5692,18 @@ static int dsi_runtime_suspend(struct device *dev) ...@@ -5678,12 +5692,18 @@ static int dsi_runtime_suspend(struct device *dev)
static int dsi_runtime_resume(struct device *dev) static int dsi_runtime_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev);
struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
int r; int r;
r = dispc_runtime_get(); r = dispc_runtime_get();
if (r) if (r)
return r; return r;
dsi->is_enabled = true;
/* ensure the irq handler sees the is_enabled value */
smp_wmb();
return 0; return 0;
} }
......
...@@ -457,7 +457,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min, ...@@ -457,7 +457,7 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul); fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul);
for (fckd = fckd_start; fckd >= fckd_stop; --fckd) { for (fckd = fckd_start; fckd >= fckd_stop; --fckd) {
fck = prate / fckd * m; fck = DIV_ROUND_UP(prate, fckd) * m;
if (func(fck, data)) if (func(fck, data))
return true; return true;
...@@ -506,7 +506,7 @@ static int dss_setup_default_clock(void) ...@@ -506,7 +506,7 @@ static int dss_setup_default_clock(void)
fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier, fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
max_dss_fck); max_dss_fck);
fck = prate / fck_div * dss.feat->dss_fck_multiplier; fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier;
} }
r = dss_set_fck_rate(fck); r = dss_set_fck_rate(fck);
......
...@@ -131,12 +131,6 @@ struct dsi_clock_info { ...@@ -131,12 +131,6 @@ struct dsi_clock_info {
u16 lp_clk_div; u16 lp_clk_div;
}; };
struct reg_field {
u16 reg;
u8 high;
u8 low;
};
struct dss_lcd_mgr_config { struct dss_lcd_mgr_config {
enum dss_io_pad_mode io_pad_mode; enum dss_io_pad_mode io_pad_mode;
......
...@@ -347,17 +347,17 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts) ...@@ -347,17 +347,17 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
case 96000: case 96000:
case 192000: case 192000:
if (deep_color == 125) if (deep_color == 125)
if (pclk == 27027 || pclk == 74250) if (pclk == 27027000 || pclk == 74250000)
deep_color_correct = true; deep_color_correct = true;
if (deep_color == 150) if (deep_color == 150)
if (pclk == 27027) if (pclk == 27027000)
deep_color_correct = true; deep_color_correct = true;
break; break;
case 44100: case 44100:
case 88200: case 88200:
case 176400: case 176400:
if (deep_color == 125) if (deep_color == 125)
if (pclk == 27027) if (pclk == 27027000)
deep_color_correct = true; deep_color_correct = true;
break; break;
default: default:
...@@ -418,7 +418,7 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts) ...@@ -418,7 +418,7 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
} }
} }
/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
*cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); *cts = (pclk/1000) * (*n / 128) * deep_color / (sample_freq / 10);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment