[MSM] Backported a lot of stuff from 2.6.35 and 2.6.32.59 kernels, compiles and tested on device

This commit is contained in:
Shantanu Gupta 2012-05-03 18:49:51 +05:30
parent bffda154f5
commit 48322595f9
75 changed files with 3506 additions and 1762 deletions

View File

@ -404,6 +404,7 @@ CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_ALIGNMENT_TRAP=y
CONFIG_ALLOW_CPU_ALIGNMENT=y
# CONFIG_UACCESS_WITH_MEMCPY is not set
#

View File

@ -382,11 +382,13 @@ ENDPROC(sys_clone_wrapper)
sys_sigreturn_wrapper:
add r0, sp, #S_OFF
mov why, #0 @ prevent syscall restart handling
b sys_sigreturn
ENDPROC(sys_sigreturn_wrapper)
sys_rt_sigreturn_wrapper:
add r0, sp, #S_OFF
mov why, #0 @ prevent syscall restart handling
b sys_rt_sigreturn
ENDPROC(sys_rt_sigreturn_wrapper)

View File

@ -158,10 +158,10 @@ __secondary_data:
* registers.
*/
__enable_mmu:
#ifdef CONFIG_ALIGNMENT_TRAP
orr r0, r0, #CR_A
#else
#ifdef CONFIG_ALLOW_CPU_ALIGNMENT
bic r0, r0, #CR_A
#else
orr r0, r0, #CR_A
#endif
#ifdef CONFIG_CPU_DCACHE_DISABLE
bic r0, r0, #CR_C

View File

@ -22,6 +22,7 @@
#include <linux/errno.h>
#include <linux/cpufreq.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
@ -62,6 +63,19 @@ struct clkctl_acpu_speed {
unsigned axiclk_khz;
};
static unsigned long max_axi_rate;
struct regulator {
struct device *dev;
struct list_head list;
int uA_load;
int min_uV;
int max_uV;
char *supply_name;
struct device_attribute dev_attr;
struct regulator_dev *rdev;
};
/* clock sources */
#define CLK_TCXO 0 /* 19.2 MHz */
#define CLK_GLOBAL_PLL 1 /* 768 MHz */
@ -76,135 +90,46 @@ struct clkctl_acpu_speed {
#define SRC_PLL1 3 /* 768 MHz */
struct clkctl_acpu_speed acpu_freq_tbl[] = {
#ifdef CONFIG_HTCLEO_UNDERVOLT_1000
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 1000, 14000 },
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 1000, 14000},
{ 96000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 1000, 14000 },
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 1000, 14000 },
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 1000, 29000 },
//{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 1000, 29000 },
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 1000, 58000 },
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 1000, 117000 },
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1000, 117000 },
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1025, 117000 },
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1050, 117000 },
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1050, 117000 },
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1075, 117000 },
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1100, 117000 },
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1125, 117000 },
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1150, 117000 },
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1150, 128000 },
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1175, 128000 },
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1200, 128000 },
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1200, 128000 },
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1225, 128000 },
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1225, 128000 },
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1225, 128000 },
#elif CONFIG_HTCLEO_UNDERVOLT_925
// should work with most of HD2s
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 925, 14000 },
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 925, 14000 },
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 925, 29000 },
//{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 925, 29000 },
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 950, 58000 },
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 975, 117000 },
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1000, 117000 },
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1025, 117000 },
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1050, 117000 },
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1050, 117000 },
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1075, 117000 },
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1100, 117000 },
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1125, 117000 },
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1150, 117000 },
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1150, 128000 },
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1175, 128000 },
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1200, 128000 },
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1200, 128000 },
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1225, 128000 },
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1225, 128000 },
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1225, 128000 },
#elif CONFIG_HTCLEO_UNDERVOLT_800
// not working yet
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 850, 14000 },
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 850, 14000 },
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 850, 29000 },
//{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 850, 29000 },
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 850, 58000 },
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 875, 117000 },
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 900, 117000 },
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 925, 117000 },
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 950, 117000 },
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 950, 117000 },
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 975, 117000 },
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1000, 117000 },
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1025, 117000 },
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1050, 117000 },
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1125, 128000 },
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1125, 128000 },
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1150, 128000 },
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1150, 128000 },
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1175, 128000 },
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1175, 128000 },
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1200, 128000 },
#else
{ 19200, CCTL(CLK_TCXO, 1), SRC_RAW, 0, 0, 1050, 14000},
{ 128000, CCTL(CLK_TCXO, 1), SRC_AXI, 0, 0, 1050, 14000 },
{ 245000, CCTL(CLK_MODEM_PLL, 1), SRC_RAW, 0, 0, 1050, 29000 },
/* Work arround for acpu resume hung, GPLL is turn off by arm9 */
/*{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 1050, 29000 },*/
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 1050, 58000 },
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 1050, 117000 },
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1050, 117000 },
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1075, 117000 },
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1100, 117000 },
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1100, 117000 },
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1125, 117000 },
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1150, 117000 },
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1175, 117000 },
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1200, 117000 },
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1200, 128000 },
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1225, 128000 },
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1250, 128000 },
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1275, 128000 },
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1300, 128000 },
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1300, 128000 },
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1300, 128000 },
#endif
#ifdef CONFIG_HTCLEO_OVERCLOCK
#ifdef CONFIG_HTCLEO_UNDERVOLT_1000
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1225, 128000 },
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1250, 128000 },
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1275, 128000 },
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
#elif CONFIG_HTCLEO_UNDERVOLT_925
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1225, 128000 },
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1250, 128000 },
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1275, 128000 },
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
#elif CONFIG_HTCLEO_UNDERVOLT_800
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1225, 128000 },
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1250, 128000 },
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1275, 128000 },
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
#else
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1300, 128000 },
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1300, 128000 },
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1300, 128000 },
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1325, 128000 },
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
#endif
/* Work arround for acpu resume hung, GPLL is turn off by arm9 */
/*{ 256000, CCTL(CLK_GLOBAL_PLL, 3), SRC_RAW, 0, 0, 1050, 29000 },*/
{ 384000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0A, 0, 1000, 58000 },
{ 422400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0B, 0, 1000, 117000 },
{ 460800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0C, 0, 1000, 117000 },
{ 499200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0D, 0, 1050, 117000 },
{ 537600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0E, 0, 1050, 117000 },
{ 576000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x0F, 0, 1050, 117000 },
{ 614400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x10, 0, 1075, 117000 },
{ 652800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x11, 0, 1100, 117000 },
{ 691200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x12, 0, 1125, 117000 },
{ 729600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x13, 0, 1150, 117000 },
{ 768000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x14, 0, 1150, 128000 },
{ 806400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x15, 0, 1175, 128000 },
{ 844800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x16, 0, 1225, 128000 },
{ 883200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x17, 0, 1250, 128000 },
{ 921600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x18, 0, 1300, 128000 },
{ 960000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x19, 0, 1300, 128000 },
{ 998400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1A, 0, 1300, 128000 },
#ifdef CONFIG_HTCLEO_OVERCLOCK
{ 1036800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1B, 0, 1300, 128000 },
{ 1075200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1C, 0, 1300, 128000 },
{ 1113600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1D, 0, 1300, 128000 },
{ 1152000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1E, 0, 1300, 128000 },
{ 1190400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x1F, 0, 1325, 128000 },
#endif
#ifdef CONFIG_HTCLEO_EXOVERCLOCK
{ 1228800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x20, 0, 1325, 128000 },
{ 1267200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x21, 0, 1350, 128000 },
{ 1305600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x22, 0, 1350, 128000 },
{ 1344000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x23, 0, 1350, 128000 },
{ 1382400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x24, 0, 1350, 128000 },
{ 1420800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x25, 0, 1350, 128000 },
{ 1459200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x26, 0, 1350, 128000 },
{ 1497600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x27, 0, 1350, 128000 },
{ 1536000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x28, 0, 1350, 128000 },
{ 1228800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x20, 0, 1325, 128000 },
{ 1267200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x21, 0, 1350, 128000 },
{ 1305600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x22, 0, 1350, 128000 },
{ 1344000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x23, 0, 1350, 128000 },
{ 1382400, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x24, 0, 1350, 128000 },
{ 1420800, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x25, 0, 1350, 128000 },
{ 1459200, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x26, 0, 1350, 128000 },
{ 1497600, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x27, 0, 1350, 128000 },
{ 1536000, CCTL(CLK_TCXO, 1), SRC_SCPLL, 0x28, 0, 1350, 128000 },
#endif
{ 0 },
};
@ -231,11 +156,10 @@ static void __init acpuclk_init_cpufreq_table(void)
freq_table[i].index = i;
freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
/* Skip speeds we don't want */
if ( acpu_freq_tbl[i].acpu_khz == 19200 ||
//acpu_freq_tbl[i].acpu_khz == 128000 ||
acpu_freq_tbl[i].acpu_khz == 256000)
continue;
/* Skip speeds using the global pll */
if (acpu_freq_tbl[i].acpu_khz == 256000 ||
acpu_freq_tbl[i].acpu_khz == 19200)
continue;
vdd = acpu_freq_tbl[i].vdd;
/* Allow mpll and the first scpll speeds */
@ -269,6 +193,7 @@ struct clock_state {
unsigned long wait_for_irq_khz;
struct clk* clk_ebi1;
struct regulator *regulator;
int (*acpu_set_vdd) (int mvolts);
};
static struct clock_state drv_state = { 0 };
@ -345,11 +270,10 @@ static void scpll_set_freq(uint32_t lval)
dmb();
/* wait for frequency switch to finish */
while (readl(SCPLL_STATUS_ADDR) & 0x1)
;
while (readl(SCPLL_STATUS_ADDR) & 0x1);
/* completion bit is not reliable for SHOT switch */
udelay(25);
udelay(15);
}
/* write the new L val and switch mode */
@ -363,8 +287,7 @@ static void scpll_set_freq(uint32_t lval)
dmb();
/* wait for frequency switch to finish */
while (readl(SCPLL_STATUS_ADDR) & 0x1)
;
while (readl(SCPLL_STATUS_ADDR) & 0x1);
}
/* this is still a bit weird... */
@ -625,13 +548,20 @@ static void __init acpuclk_init(void)
}
drv_state.current_speed = speed;
for (speed = acpu_freq_tbl; speed->acpu_khz; speed++)
for (speed = acpu_freq_tbl; speed->acpu_khz; speed++) {
speed->lpj = cpufreq_scale(loops_per_jiffy,
init_khz, speed->acpu_khz);
max_axi_rate = speed->axiclk_khz * 1000;
}
loops_per_jiffy = drv_state.current_speed->lpj;
}
unsigned long acpuclk_get_max_axi_rate(void)
{
return max_axi_rate;
}
unsigned long acpuclk_get_rate(void)
{
return drv_state.current_speed->acpu_khz;
@ -674,6 +604,7 @@ void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us;
drv_state.power_collapse_khz = clkdata->power_collapse_khz;
drv_state.wait_for_irq_khz = clkdata->wait_for_irq_khz;
drv_state.acpu_set_vdd = acpuclk_set_vdd_level;
if (clkdata->mpll_khz)
acpu_mpll->acpu_khz = clkdata->mpll_khz;
@ -708,7 +639,7 @@ ssize_t acpuclk_get_vdd_levels_str(char *buf)
void acpuclk_set_vdd(unsigned acpu_khz, int vdd)
{
int i;
vdd = vdd / 25 * 25; //! regulator only accepts multiples of 25 (mV)
vdd = (vdd / HTCLEO_TPS65023_UV_STEP_MV) * HTCLEO_TPS65023_UV_STEP_MV;
mutex_lock(&drv_state.lock);
for (i = 0; acpu_freq_tbl[i].acpu_khz; i++)
{
@ -722,5 +653,16 @@ void acpuclk_set_vdd(unsigned acpu_khz, int vdd)
}
mutex_unlock(&drv_state.lock);
}
unsigned int acpuclk_get_vdd_min(void)
{
return HTCLEO_TPS65023_MIN_UV_MV;
}
unsigned int acpuclk_get_vdd_max(void)
{
return HTCLEO_TPS65023_MAX_UV_MV;
}
unsigned int acpuclk_get_vdd_step(void)
{
return HTCLEO_TPS65023_UV_STEP_MV;
}
#endif

View File

@ -24,6 +24,7 @@
#include <asm/gpio.h>
#include <mach/gpio.h>
#include <mach/htc_headset_mgr.h>
#include <mach/board-htcleo-audio.h>
#include "board-htcleo.h"
#include "devices.h"

View File

@ -39,7 +39,6 @@
#define HTCLEO_DEFAULT_BACKLIGHT_BRIGHTNESS 255
static struct led_trigger *htcleo_lcd_backlight;
static int auto_bl_state=0;
static DEFINE_MUTEX(htcleo_backlight_lock);

View File

@ -118,7 +118,7 @@ int lightsensor_read_value(uint32_t *val)
}
*val = data[1] | (data[0] << 8);
D("lsensor adc = %d\n", *val);
D("lsensor adc = %u\n", *val); /* val is unsigned */
return 0;
}

View File

@ -30,6 +30,7 @@
#include <mach/vreg.h>
#include <mach/gpio.h>
#include <mach/board-htcleo-mmc.h>
#include "board-htcleo.h"
#include "devices.h"
@ -391,7 +392,7 @@ static int __init htcleommc_dbg_init(void)
{
struct dentry *dent;
if (!machine_is_htcleo() && !machine_is_htcleo())
if (!machine_is_htcleo())
return 0;
dent = debugfs_create_dir("htcleo_mmc_dbg", 0);

View File

@ -55,7 +55,9 @@
#ifdef CONFIG_SERIAL_BCM_BT_LPM
#include <mach/bcm_bt_lpm.h>
#endif
#ifdef CONFIG_PERFLOCK
#include <mach/perflock.h>
#endif
#include <mach/htc_headset_mgr.h>
#include <mach/htc_headset_gpio.h>
@ -395,10 +397,9 @@ static uint32_t flashlight_gpio_table[] =
PCOM_GPIO_CFG(HTCLEO_GPIO_FLASHLIGHT_FLASH, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA),
};
static int config_htcleo_flashlight_gpios(void)
static void config_htcleo_flashlight_gpios(void)
{
config_gpio_table(flashlight_gpio_table, ARRAY_SIZE(flashlight_gpio_table));
return 0;
}
static struct flashlight_platform_data htcleo_flashlight_data =
@ -748,28 +749,6 @@ static struct platform_device qsd_device_spi = {
///////////////////////////////////////////////////////////////////////
// KGSL (HW3D support)#include <linux/android_pmem.h>
///////////////////////////////////////////////////////////////////////
static struct resource msm_kgsl_resources[] =
{
{
.name = "kgsl_reg_memory",
.start = MSM_GPU_REG_PHYS,
.end = MSM_GPU_REG_PHYS + MSM_GPU_REG_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "kgsl_phys_memory",
.start = MSM_GPU_PHYS_BASE,
.end = MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
.start = INT_GRAPHICS,
.end = INT_GRAPHICS,
.flags = IORESOURCE_IRQ,
},
};
static int htcleo_kgsl_power_rail_mode(int follow_clk)
{
int mode = follow_clk ? 0 : 1;
@ -786,16 +765,7 @@ static int htcleo_kgsl_power(bool on)
return msm_proc_comm(cmd, &rail_id, 0);
}
static struct platform_device msm_kgsl_device =
{
.name = "kgsl",
.id = -1,
.resource = msm_kgsl_resources,
.num_resources = ARRAY_SIZE(msm_kgsl_resources),
};
#ifdef CONFIG_MSM_KGSL
/* start kgsl */
/* start kgsl-3d0 */
static struct resource kgsl_3d0_resources[] = {
{
.name = KGSL_3D0_REG_MEMORY,
@ -843,9 +813,7 @@ struct platform_device msm_kgsl_3d0 = {
.platform_data = &kgsl_3d0_pdata,
},
};
/* end kgsl */
#endif
/* end kgsl-3d0 */
///////////////////////////////////////////////////////////////////////
// Memory
///////////////////////////////////////////////////////////////////////
@ -897,7 +865,7 @@ static struct platform_device android_pmem_mdp_device = {
static struct platform_device android_pmem_adsp_device = {
.name = "android_pmem",
.id = 4,
.id = 1, /* 4 */
.dev = {
.platform_data = &android_pmem_adsp_pdata,
},
@ -905,7 +873,7 @@ static struct platform_device android_pmem_adsp_device = {
static struct platform_device android_pmem_venc_device = {
.name = "android_pmem",
.id = 5,
.id = 3, /* 5 */
.dev = {
.platform_data = &android_pmem_venc_pdata,
},
@ -1083,6 +1051,7 @@ static struct msm_acpu_clock_platform_data htcleo_clock_data = {
// .wait_for_irq_khz = 19200, // TCXO
};
#ifdef CONFIG_PERFLOCK
static unsigned htcleo_perf_acpu_table[] = {
245000000,
576000000,
@ -1093,6 +1062,8 @@ static struct perflock_platform_data htcleo_perflock_data = {
.perf_acpu_table = htcleo_perf_acpu_table,
.table_size = ARRAY_SIZE(htcleo_perf_acpu_table),
};
#endif
///////////////////////////////////////////////////////////////////////
// Reset
///////////////////////////////////////////////////////////////////////
@ -1139,7 +1110,9 @@ static void __init htcleo_init(void)
msm_acpu_clock_init(&htcleo_clock_data);
#ifdef CONFIG_PERFLOCK
perflock_init(&htcleo_perflock_data);
#endif
#if defined(CONFIG_MSM_SERIAL_DEBUGGER)
msm_serial_debug_init(MSM_UART1_PHYS, INT_UART1,

View File

@ -178,7 +178,8 @@
/* Voltage driver */
#define HTCLEO_TPS65023_MIN_UV_MV (800)
#define HTCLEO_TPS65023_MAX_UV_MV (1350)
#define HTCLEO_TPS65023_MAX_UV_MV (1375)
#define HTCLEO_TPS65023_UV_STEP_MV (25)
/* LEDS */
#define LED_RGB (1 << 0)
@ -196,11 +197,12 @@ struct microp_led_platform_data {
int num_leds;
};
int htcleo_pm_set_vreg(int enable, unsigned id);
int __init htcleo_init_panel(void);
int htcleo_is_nand_boot(void);
unsigned htcleo_get_vbus_state(void);
void config_camera_on_gpios(void);
void config_camera_off_gpios(void);
int is_valid_mac_address(char *mac);
#endif /* __ARCH_ARM_MACH_MSM_BOARD_HTCLEO_H */

View File

@ -34,6 +34,8 @@
//#define ENABLE_CLOCK_INFO 1
extern struct clk msm_clocks[];
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clocks_lock);
static LIST_HEAD(clocks);
@ -233,8 +235,16 @@ struct mdns_clock_params msm_clock_freq_parameters[] = {
MSM_CLOCK_REG(64000000,0x19, 0x60, 0x30, 0, 2, 4, 1, 245760000), /* BT, 4000000 (*16) */
};
int status_set_grp_clk = 0;
int i_set_grp_clk = 0;
int control_set_grp_clk;
static void set_grp_clk( int on )
{
int i = 0;
int status = 0;
int control;
if ( on != 0 )
{
//axi_reset
@ -274,8 +284,7 @@ static void set_grp_clk( int on )
writel(readl(MSM_CLK_CTL_BASE) |0x8, MSM_CLK_CTL_BASE);
//grp MD
writel(readl(MSM_CLK_CTL_BASE+0x80) |0x1, MSM_CLK_CTL_BASE+0x80); //PRPH_WEB_NS_REG
int i = 0;
int status = 0;
while ( status == 0 && i < 100) {
i++;
status = readl(MSM_CLK_CTL_BASE+0x84) & 0x1;
@ -297,7 +306,7 @@ static void set_grp_clk( int on )
writel(readl(MSM_CLK_CTL_BASE+0x290) |0x4, MSM_CLK_CTL_BASE+0x290); //MSM_RAIL_CLAMP_IO
writel( 0x11f, MSM_CLK_CTL_BASE+0x284); //VDD_GRP_GFS_CTL
int control = readl(MSM_CLK_CTL_BASE+0x288); //VDD_VDC_GFS_CTL
control = readl(MSM_CLK_CTL_BASE+0x288); //VDD_VDC_GFS_CTL
if ( control & 0x100 )
writel(readl(MSM_CLK_CTL_BASE) &(~(0x8)), MSM_CLK_CTL_BASE);
}
@ -1291,5 +1300,18 @@ static int __init clock_late_init(void)
//pr_info("reset imem_config\n");
return 0;
}
late_initcall(clock_late_init);
struct clk_ops clk_ops_pcom = {
.enable = pc_clk_enable,
.disable = pc_clk_disable,
.auto_off = pc_clk_disable,
// .reset = pc_clk_reset,
.set_rate = pc_clk_set_rate,
.set_min_rate = pc_clk_set_min_rate,
.set_max_rate = pc_clk_set_max_rate,
.set_flags = pc_clk_set_flags,
.get_rate = pc_clk_get_rate,
.is_enabled = pc_clk_is_enabled,
// .round_rate = pc_clk_round_rate,
};

View File

@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <mach/clk.h>
#include <linux/spinlock.h>
#include <linux/fs.h>
#include <linux/debugfs.h>

View File

@ -17,6 +17,13 @@
*
*/
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/sched.h>
#include <linux/suspend.h>
#include <linux/cpufreq.h>
#include <linux/earlysuspend.h>
#include <linux/init.h>

View File

@ -138,13 +138,14 @@ dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd,
complete(&cmd->complete);
}
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
int msm_dmov_exec_cmd(unsigned id, unsigned int crci_mask, unsigned int cmdptr)
{
struct msm_dmov_exec_cmdptr_cmd cmd;
PRINT_FLOW("dmov_exec_cmdptr(%d, %x)\n", id, cmdptr);
cmd.dmov_cmd.cmdptr = cmdptr;
cmd.dmov_cmd.crci_mask = crci_mask;
cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func;
cmd.dmov_cmd.execute_func = NULL;
cmd.id = id;

View File

@ -0,0 +1,29 @@
/* board-htcleo-mmc.h
*
* Copyright (C) 2011 marc1706
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#ifndef HTCLEO_AUDIO_H
#define HTCLEO_AUDIO_H
void htcleo_headset_enable(int en);
void htcleo_speaker_enable(int en);
void htcleo_receiver_enable(int en);
void htcleo_bt_sco_enable(int en);
void htcleo_mic_enable(int en);
void htcleo_analog_init(void);
int htcleo_get_rx_vol(uint8_t hw, int level);
void __init htcleo_audio_init(void);
#endif // HTCLEO_AUDIO_H

View File

@ -136,4 +136,14 @@ struct microp_i2c_client_data {
int microp_i2c_read(uint8_t addr, uint8_t *data, int length);
int microp_i2c_write(uint8_t addr, uint8_t *data, int length);
int capella_cm3602_power(int pwr_device, uint8_t enable);
int microp_read_gpo_status(uint16_t *status);
int microp_gpo_enable(uint16_t gpo_mask);
int microp_gpo_disable(uint16_t gpo_mask);
#ifdef CONFIG_HAS_EARLYSUSPEND
void microp_early_suspend(struct early_suspend *h);
void microp_early_resume(struct early_suspend *h);
#endif // CONFIG_HAS_EARLYSUSPEND
#endif

View File

@ -0,0 +1,31 @@
/* board-htcleo-mmc.h
*
* Copyright (C) 2011 marc1706
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#ifndef HTCLEO_MMC_H
#define HTCLEO_MMC_H
static bool opt_disable_sdcard;
static void (*wifi_status_cb)(int card_present, void *dev_id);
static void *wifi_status_cb_devid;
static int htcleo_wifi_power_state;
static int htcleo_wifi_reset_state;
int htcleo_wifi_set_carddetect(int val);
int htcleo_wifi_power(int on);
int htcleo_wifi_reset(int on);
int __init htcleo_init_mmc(unsigned debug_uart);
#endif // HTCLEO_MMC_H

View File

@ -178,6 +178,8 @@ enum {
BOOTMODE_OFFMODE_CHARGING = 0x5,
};
void msm_hsusb_set_vbus_state(int online);
#define MSM_MAX_DEC_CNT 14
/* 7k target ADSP information */
/* Bit 23:0, for codec identification like mp3, wav etc *

View File

@ -32,6 +32,7 @@
#define NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS 16
#define NUM_STAT_OUTPUT_BUFFERS 3
#define NUM_AF_STAT_OUTPUT_BUFFERS 3
#define max_control_command_size 150
enum msm_queue {
MSM_CAM_Q_CTRL, /* control command or control command status */

View File

@ -51,4 +51,7 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate);
int clk_reset(struct clk *clk, enum clk_reset_action action);
int clk_set_flags(struct clk *clk, unsigned long flags);
unsigned long acpuclk_get_max_axi_rate(void);
#endif

View File

@ -0,0 +1,47 @@
/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __ARCH_ARM_MACH_MSM_DEBUG_MM_H_
#define __ARCH_ARM_MACH_MSM_DEBUG_MM_H_
/* The below macro removes the directory path name and retains only the
* file name to avoid long path names in log messages that comes as
* part of __FILE__ to compiler.
*/
#define __MM_FILE__ strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/')+1) : \
__FILE__
#define MM_DBG(fmt, args...) pr_debug("[%s] " fmt,\
__func__, ##args)
#define MM_INFO(fmt, args...) pr_info("[%s:%s] " fmt,\
__MM_FILE__, __func__, ##args)
#define MM_ERR(fmt, args...) pr_err("[%s:%s] " fmt,\
__MM_FILE__, __func__, ##args)
#endif /* __ARCH_ARM_MACH_MSM_DEBUG_MM_H_ */

View File

@ -27,6 +27,7 @@ struct msm_dmov_errdata {
struct msm_dmov_cmd {
struct list_head list;
unsigned int cmdptr;
unsigned int crci_mask;
void (*complete_func)(struct msm_dmov_cmd *cmd,
unsigned int result,
struct msm_dmov_errdata *err);
@ -38,7 +39,7 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd);
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
void msm_dmov_flush(unsigned int id);
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
int msm_dmov_exec_cmd(unsigned id, unsigned int crci_mask, unsigned int cmdptr);

View File

@ -311,6 +311,7 @@
#define INT_MDDI_CLIENT INT_MDC
#define INT_NAND_WR_ER_DONE INT_EBI2_WR_ER_DONE
#define INT_NAND_OP_DONE INT_EBI2_OP_DONE
#define INT_GRAPHICS INT_GRP_3D
#define NR_SIRC_IRQS 0

View File

@ -27,10 +27,12 @@ struct mddi_info;
#define MSM_MDP_OUT_IF_FMT_RGB888 2
/* mdp override operations */
#define MSM_MDP_PANEL_IGNORE_PIXEL_DATA (1 << 0)
#define MSM_MDP_PANEL_IGNORE_PIXEL_DATA (1 << 0)
#define MSM_MDP_PANEL_FLIP_UD (1 << 1)
#define MSM_MDP_PANEL_FLIP_LR (1 << 2)
#define MSM_MDP4_MDDI_DMA_SWITCH (1 << 3)
#define MSM_MDP_DMA_PACK_ALIGN_LSB (1 << 4)
#define MSM_MDP_RGB_PANEL_SELF_REFRESH (1 << 5)
/* mddi type */
#define MSM_MDP_MDDI_TYPE_I 0
@ -190,6 +192,7 @@ struct msm_lcdc_panel_ops {
int (*uninit)(struct msm_lcdc_panel_ops *);
int (*blank)(struct msm_lcdc_panel_ops *);
int (*unblank)(struct msm_lcdc_panel_ops *);
int (*shutdown)(struct msm_lcdc_panel_ops *);
};
struct msm_lcdc_platform_data {
@ -211,6 +214,8 @@ struct msm_tvenc_platform_data {
struct mdp_blit_req;
struct fb_info;
struct mdp_overlay;
struct msmfb_overlay_data;
struct mdp_device {
struct device dev;
void (*dma)(struct mdp_device *mdp, uint32_t addr,
@ -227,14 +232,17 @@ struct mdp_device {
int (*overlay_unset)(struct mdp_device *mdp, struct fb_info *fb,
int ndx);
int (*overlay_play)(struct mdp_device *mdp, struct fb_info *fb,
struct msmfb_overlay_data *req, struct file *p_src_file);
struct msmfb_overlay_data *req, struct file **p_src_file);
#endif
void (*set_grp_disp)(struct mdp_device *mdp, uint32_t disp_id);
void (*configure_dma)(struct mdp_device *mdp);
int (*check_output_format)(struct mdp_device *mdp, int bpp);
int (*set_output_format)(struct mdp_device *mdp, int bpp);
void (*set_panel_size)(struct mdp_device *mdp, int width, int height);
unsigned color_format;
unsigned overrides;
uint32_t width; /*panel width*/
uint32_t height; /*panel height*/
};
struct class_interface;

View File

@ -19,12 +19,14 @@
#define AUDIO_FLAG_READ 0
#define AUDIO_FLAG_WRITE 1
#define AUDIO_FLAG_INCALL_MIXED 2
struct audio_buffer {
dma_addr_t phys;
void *data;
uint32_t size;
uint32_t used; /* 1 = CPU is waiting for DSP to consume this buf */
uint32_t actual_size; /* actual number of bytes read by DSP */
};
struct audio_client {
@ -79,8 +81,10 @@ struct audio_client *q6audio_open_mp3(uint32_t bufsz, uint32_t rate,
struct audio_client *q6fm_open(void);
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate,
uint32_t flags, void *data, uint32_t acdb_id);
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t samplerate,
uint32_t channels, uint32_t bitrate,
uint32_t stream_format, uint32_t flags,
uint32_t acdb_id);
struct audio_client *q6audio_open_qcelp(uint32_t bufsz, uint32_t rate,
void *data, uint32_t acdb_id);
@ -102,7 +106,7 @@ int q6audio_set_tx_mute(int mute);
int q6audio_reinit_acdb(char* filename);
int q6audio_update_acdb(uint32_t id_src, uint32_t id_dst);
int q6audio_set_rx_volume(int level);
int q6audio_set_tx_volume(int level);
int q6audio_set_tx_volume(int mute);
int q6audio_set_stream_volume(struct audio_client *ac, int vol);
int q6audio_set_tx_dev_volume(int device_id, int level);
int q6audio_get_tx_dev_volume(int device_id);

View File

@ -132,6 +132,8 @@ uint32_t msm_rpc_get_vers(struct msm_rpc_endpoint *ept);
/* check if server version can handle client requested version */
int msm_rpc_is_compatible_version(uint32_t server_version,
uint32_t client_version);
struct msm_rpc_endpoint *msm_rpc_connect_compatible(uint32_t prog,
uint32_t vers, unsigned flags);
int msm_rpc_close(struct msm_rpc_endpoint *ept);
int msm_rpc_write(struct msm_rpc_endpoint *ept,
@ -164,7 +166,7 @@ struct msm_rpc_xdr {
void *in_buf;
uint32_t in_size;
uint32_t in_index;
struct mutex in_lock;
wait_queue_head_t in_buf_wait_q;
void *out_buf;
uint32_t out_size;
@ -174,6 +176,22 @@ struct msm_rpc_xdr {
struct msm_rpc_endpoint *ept;
};
int xdr_send_int8(struct msm_rpc_xdr *xdr, const int8_t *value);
int xdr_send_uint8(struct msm_rpc_xdr *xdr, const uint8_t *value);
int xdr_send_int16(struct msm_rpc_xdr *xdr, const int16_t *value);
int xdr_send_uint16(struct msm_rpc_xdr *xdr, const uint16_t *value);
int xdr_send_int32(struct msm_rpc_xdr *xdr, const int32_t *value);
int xdr_send_uint32(struct msm_rpc_xdr *xdr, const uint32_t *value);
int xdr_send_bytes(struct msm_rpc_xdr *xdr, const void **data, uint32_t *size);
int xdr_recv_int8(struct msm_rpc_xdr *xdr, int8_t *value);
int xdr_recv_uint8(struct msm_rpc_xdr *xdr, uint8_t *value);
int xdr_recv_int16(struct msm_rpc_xdr *xdr, int16_t *value);
int xdr_recv_uint16(struct msm_rpc_xdr *xdr, uint16_t *value);
int xdr_recv_int32(struct msm_rpc_xdr *xdr, int32_t *value);
int xdr_recv_uint32(struct msm_rpc_xdr *xdr, uint32_t *value);
int xdr_recv_bytes(struct msm_rpc_xdr *xdr, void **data, uint32_t *size);
struct msm_rpc_server
{
struct list_head list;

View File

@ -63,6 +63,8 @@ int smd_wait_until_writable(smd_channel_t *ch, int bytes);
#endif
int smd_wait_until_opened(smd_channel_t *ch, int timeout_us);
int smd_total_fifo_size(smd_channel_t *ch);
typedef enum
{
SMD_PORT_DS = 0,

View File

@ -142,13 +142,15 @@ int msm_irq_idle_sleep_allowed(void);
int msm_irq_pending(void);
int clks_allow_tcxo_locked_debug(void);
extern int board_mfg_mode(void);
extern char * board_get_mfg_sleep_gpio_table(void);
extern unsigned long * board_get_mfg_sleep_gpio_table(void);
extern void gpio_set_diag_gpio_table(unsigned long * dwMFG_gpio_table);
extern void wait_rmt_final_call_back(int timeout);
#ifdef CONFIG_AXI_SCREEN_POLICY
static int axi_rate;
static int sleep_axi_rate;
static struct clk *axi_clk;
#endif
static uint32_t *msm_pm_reset_vector;
static uint32_t msm_pm_max_sleep_time;
@ -654,8 +656,8 @@ static int msm_wakeup_after; /* default, no wakeup by alarm */
static int msm_power_wakeup_after(const char *val, struct kernel_param *kp)
{
int ret;
struct uart_port *port;
struct msm_port *msm_port;
//struct uart_port *port;
//struct msm_port *msm_port;
ret = param_set_int(val, kp);
printk(KERN_INFO "+msm_power_wakeup_after, ret=%d\r\n", ret);
@ -681,7 +683,7 @@ static void msm_pm_power_off(void)
pmic_glb_power_down();
#if CONFIG_MSM_RMT_STORAGE_SERVER
#ifdef CONFIG_MSM_RMT_STORAGE_SERVER
printk(KERN_INFO "from %s\r\n", __func__);
wait_rmt_final_call_back(10);
printk(KERN_INFO "back %s\r\n", __func__);
@ -715,7 +717,7 @@ void msm_pm_flush_console(void)
}
#if defined(CONFIG_MACH_HTCLEO)
static void htcleo_save_reset_reason()
static void htcleo_save_reset_reason(void)
{
/* save restart_reason to be accesible in bootloader @ ramconsole - 0x1000*/
uint32_t *bootloader_reset_reason = ioremap(0x2FFB0000, PAGE_SIZE);
@ -728,7 +730,7 @@ static void htcleo_save_reset_reason()
}
#endif
static void msm_pm_restart(char str)
static void msm_pm_restart(char str, const char *cmd)
{
msm_pm_flush_console();
@ -742,7 +744,7 @@ static void msm_pm_restart(char str)
else
msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);
#if CONFIG_MSM_RMT_STORAGE_SERVER
#ifdef CONFIG_MSM_RMT_STORAGE_SERVER
printk(KERN_INFO "from %s\r\n", __func__);
wait_rmt_final_call_back(10);
printk(KERN_INFO "back %s\r\n", __func__);
@ -858,6 +860,7 @@ void msm_pm_set_max_sleep_time(int64_t max_sleep_time_ns)
EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
#ifdef CONFIG_EARLYSUSPEND
#ifdef CONFIG_AXI_SCREEN_POLICY
/* axi 128 screen on, 61mhz screen off */
static void axi_early_suspend(struct early_suspend *handler)
{
@ -877,7 +880,9 @@ static struct early_suspend axi_screen_suspend = {
.resume = axi_late_resume,
};
#endif
#endif
#ifdef CONFIG_AXI_SCREEN_POLICY
static void __init msm_pm_axi_init(void)
{
#ifdef CONFIG_EARLYSUSPEND
@ -895,19 +900,18 @@ static void __init msm_pm_axi_init(void)
axi_rate = 0;
#endif
}
#endif
static int __init msm_pm_init(void)
{
pm_power_off = msm_pm_power_off;
arm_pm_restart = msm_pm_restart;
msm_pm_max_sleep_time = 0;
#if defined(CONFIG_ARCH_MSM_SCORPION)
#ifdef CONFIG_AXI_SCREEN_POLICY
msm_pm_axi_init();
#endif
#endif
register_reboot_notifier(&msm_reboot_notifier);
msm_pm_reset_vector = ioremap(0x0, PAGE_SIZE);
#if defined(CONFIG_MACH_HTCLEO)

View File

@ -14,6 +14,7 @@
*
*/
#include <linux/gpio.h>
#include <linux/module.h>
#include "devices.h"
#include "proc_comm.h"

View File

@ -1,7 +1,7 @@
/* arch/arm/mach-msm/qdsp6/aac_in.c
*
/*
* Copyright (C) 2009 Google, Inc.
* Copyright (C) 2009 HTC Corporation
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -12,8 +12,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
*/
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
@ -21,197 +22,449 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/msm_audio.h>
#include <linux/kthread.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/msm_audio_1550.h>
#include <linux/msm_audio_aac.h>
#include <mach/msm_qdsp6_audio_1550.h>
#include <mach/debug_mm.h>
#define BUFSZ (4096)
#define DMASZ (BUFSZ * 2)
#define AAC_FC_BUFF_CNT 10
#define AAC_READ_TIMEOUT 2000
struct aac_fc_buff {
struct mutex lock;
int empty;
void *data;
int size;
int actual_size;
};
#if 0
#define TRACE(x...) pr_info("Q6: "x)
#else
#define TRACE(x...) do{}while(0)
#endif
struct aac_fc {
struct task_struct *task;
wait_queue_head_t fc_wq;
struct aac_fc_buff fc_buff[AAC_FC_BUFF_CNT];
int buff_index;
};
struct aac {
struct mutex lock;
struct msm_audio_aac_enc_config cfg;
struct msm_audio_stream_config str_cfg;
struct audio_client *audio_client;
struct msm_voicerec_mode voicerec_mode;
struct aac_fc *aac_fc;
};
static DEFINE_MUTEX(aac_in_lock);
static int aac_in_opened = 0;
static struct aac_format *af;
void audio_client_dump(struct audio_client *ac);
static long aac_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int rc = 0;
switch (cmd) {
case AUDIO_SET_VOLUME:
break;
case AUDIO_GET_STATS: {
struct msm_audio_stats stats;
memset(&stats, 0, sizeof(stats));
if (copy_to_user((void*) arg, &stats, sizeof(stats)))
return -EFAULT;
return 0;
}
case AUDIO_START: {
uint32_t acdb_id;
rc = 0;
if (arg == 0) {
acdb_id = 0;
} else if (copy_from_user(&acdb_id,
(void*) arg, sizeof(acdb_id))) {
rc = -EFAULT;
break;
}
mutex_lock(&aac_in_lock);
if (file->private_data) {
rc = -EBUSY;
} else {
file->private_data = q6audio_open_aac(
BUFSZ, 48000, AUDIO_FLAG_READ, af, acdb_id);
if (!file->private_data)
rc = -ENOMEM;
}
mutex_unlock(&aac_in_lock);
break;
}
case AUDIO_STOP:
break;
case AUDIO_FLUSH:
break;
case AUDIO_SET_CONFIG: {
struct msm_audio_config config;
if (copy_from_user(&config, (void*) arg, sizeof(config))) {
rc = -EFAULT;
break;
}
if (config.sample_rate != 48000)
pr_info("only 48KHz AAC encode supported\n");
af->channel_config = config.channel_count;
break;
}
case AUDIO_GET_CONFIG: {
struct msm_audio_config config;
config.buffer_size = BUFSZ;
config.buffer_count = 2;
config.sample_rate = 48000;
config.channel_count = af->channel_config;
config.unused[0] = 0;
config.unused[1] = 0;
config.unused[2] = 0;
if (copy_to_user((void*) arg, &config, sizeof(config))) {
rc = -EFAULT;
}
break;
}
default:
rc = -EINVAL;
}
return rc;
}
static int aac_in_open(struct inode *inode, struct file *file)
{
int rc;
pr_info("aac_in: open\n");
mutex_lock(&aac_in_lock);
if (aac_in_opened) {
pr_err("aac_in: busy\n");
rc = -EBUSY;
} else {
af = kzalloc(sizeof(*af), GFP_KERNEL);
memset(af, 0, sizeof(struct aac_format));
af->sample_rate = 3; /* 48000 */
af->channel_config = 1;
af->block_formats = AUDIO_AAC_FORMAT_ADTS;
af->audio_object_type = 2; /* CAD to ADSP format */
af->bit_rate = 192000;
aac_in_opened = 1;
rc = 0;
}
mutex_unlock(&aac_in_lock);
return rc;
}
static ssize_t aac_in_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
static int q6_aac_flowcontrol(void *data)
{
struct audio_client *ac;
struct audio_buffer *ab;
const char __user *start = buf;
int xfer, res = 0;
struct aac *aac = data;
int buff_index = 0;
int xfer = 0;
struct aac_fc *fc;
ac = aac->audio_client;
fc = aac->aac_fc;
if (!ac) {
pr_err("[%s:%s] audio_client is NULL\n", __MM_FILE__, __func__);
return 0;
}
while (!kthread_should_stop()) {
ab = ac->buf + ac->cpu_buf;
if (ab->used)
wait_event(ac->wait, (ab->used == 0));
pr_debug("[%s:%s] ab->data = %p, cpu_buf = %d\n", __MM_FILE__,
__func__, ab->data, ac->cpu_buf);
xfer = ab->actual_size;
mutex_lock(&(fc->fc_buff[buff_index].lock));
if (!fc->fc_buff[buff_index].empty) {
pr_err("[%s:%s] flow control buffer[%d] not read!\n",
__MM_FILE__, __func__, buff_index);
}
if (fc->fc_buff[buff_index].size < xfer) {
pr_err("[%s:%s] buffer %d too small\n", __MM_FILE__,
__func__, buff_index);
memcpy(fc->fc_buff[buff_index].data,
ab->data, fc->fc_buff[buff_index].size);
fc->fc_buff[buff_index].empty = 0;
fc->fc_buff[buff_index].actual_size =
fc->fc_buff[buff_index].size;
} else {
memcpy(fc->fc_buff[buff_index].data, ab->data, xfer);
fc->fc_buff[buff_index].empty = 0;
fc->fc_buff[buff_index].actual_size = xfer;
}
mutex_unlock(&(fc->fc_buff[buff_index].lock));
/*wake up client, if any*/
wake_up(&fc->fc_wq);
buff_index++;
if (buff_index >= AAC_FC_BUFF_CNT)
buff_index = 0;
ab->used = 1;
q6audio_read(ac, ab);
ac->cpu_buf ^= 1;
}
return 0;
}
static long q6_aac_in_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct aac *aac = file->private_data;
int rc = 0;
int i = 0;
struct aac_fc *fc;
int size = 0;
mutex_lock(&aac->lock);
switch (cmd) {
case AUDIO_SET_VOLUME:
break;
case AUDIO_GET_STATS:
{
struct msm_audio_stats stats;
pr_debug("[%s:%s] GET_STATS\n", __MM_FILE__, __func__);
memset(&stats, 0, sizeof(stats));
if (copy_to_user((void *) arg, &stats, sizeof(stats)))
return -EFAULT;
return 0;
}
case AUDIO_START:
{
uint32_t acdb_id;
pr_debug("[%s:%s] AUDIO_START\n", __MM_FILE__, __func__);
if (arg == 0) {
acdb_id = 0;
} else {
if (copy_from_user(&acdb_id, (void *) arg,
sizeof(acdb_id))) {
rc = -EFAULT;
break;
}
}
if (aac->audio_client) {
rc = -EBUSY;
pr_err("[%s:%s] active session already existing\n",
__MM_FILE__, __func__);
break;
} else {
aac->audio_client = q6audio_open_aac(
aac->str_cfg.buffer_size,
aac->cfg.sample_rate,
aac->cfg.channels,
aac->cfg.bit_rate,
aac->cfg.stream_format,
aac->voicerec_mode.rec_mode, acdb_id);
if (aac->audio_client < 0) {
pr_err("[%s:%s] aac open session failed\n",
__MM_FILE__, __func__);
rc = -ENOMEM;
break;
}
}
/*allocate flow control buffers*/
fc = aac->aac_fc;
size = ((aac->str_cfg.buffer_size < 1543) ? 1543 :
aac->str_cfg.buffer_size);
for (i = 0; i < AAC_FC_BUFF_CNT; ++i) {
mutex_init(&(fc->fc_buff[i].lock));
fc->fc_buff[i].empty = 1;
fc->fc_buff[i].data = kmalloc(size, GFP_KERNEL);
if (fc->fc_buff[i].data == NULL) {
pr_err("[%s:%s] No memory for FC buffers\n",
__MM_FILE__, __func__);
rc = -ENOMEM;
goto fc_fail;
}
fc->fc_buff[i].size = size;
fc->fc_buff[i].actual_size = 0;
}
/*create flow control thread*/
fc->task = kthread_run(q6_aac_flowcontrol,
aac, "aac_flowcontrol");
if (IS_ERR(fc->task)) {
rc = PTR_ERR(fc->task);
pr_err("[%s:%s] error creating flow control thread\n",
__MM_FILE__, __func__);
goto fc_fail;
}
break;
fc_fail:
/*free flow control buffers*/
--i;
for (; i >= 0; i--) {
kfree(fc->fc_buff[i].data);
fc->fc_buff[i].data = NULL;
}
break;
}
case AUDIO_STOP:
pr_debug("[%s:%s] AUDIO_STOP\n", __MM_FILE__, __func__);
break;
case AUDIO_FLUSH:
break;
case AUDIO_SET_INCALL: {
pr_debug("[%s:%s] SET_INCALL\n", __MM_FILE__, __func__);
if (copy_from_user(&aac->voicerec_mode,
(void *)arg, sizeof(struct msm_voicerec_mode)))
rc = -EFAULT;
if (aac->voicerec_mode.rec_mode != AUDIO_FLAG_READ
&& aac->voicerec_mode.rec_mode !=
AUDIO_FLAG_INCALL_MIXED) {
aac->voicerec_mode.rec_mode = AUDIO_FLAG_READ;
pr_err("[%s:%s] Invalid rec_mode\n", __MM_FILE__,
__func__);
rc = -EINVAL;
}
break;
}
case AUDIO_GET_STREAM_CONFIG:
if (copy_to_user((void *)arg, &aac->str_cfg,
sizeof(struct msm_audio_stream_config)))
rc = -EFAULT;
pr_debug("[%s:%s] GET_STREAM_CONFIG: buffsz=%d, buffcnt=%d\n",
__MM_FILE__, __func__, aac->str_cfg.buffer_size,
aac->str_cfg.buffer_count);
break;
case AUDIO_SET_STREAM_CONFIG:
if (copy_from_user(&aac->str_cfg, (void *)arg,
sizeof(struct msm_audio_stream_config))) {
rc = -EFAULT;
break;
}
pr_debug("[%s:%s] SET_STREAM_CONFIG: buffsz=%d, buffcnt=%d\n",
__MM_FILE__, __func__, aac->str_cfg.buffer_size,
aac->str_cfg.buffer_count);
if (aac->str_cfg.buffer_size < 1543) {
pr_err("[%s:%s] Buffer size too small\n", __MM_FILE__,
__func__);
rc = -EINVAL;
break;
}
if (aac->str_cfg.buffer_count != 2)
pr_info("[%s:%s] Buffer count set to 2\n", __MM_FILE__,
__func__);
break;
case AUDIO_SET_AAC_ENC_CONFIG:
if (copy_from_user(&aac->cfg, (void *) arg,
sizeof(struct msm_audio_aac_enc_config))) {
rc = -EFAULT;
}
pr_debug("[%s:%s] SET_AAC_ENC_CONFIG: channels=%d, rate=%d\n",
__MM_FILE__, __func__, aac->cfg.channels,
aac->cfg.sample_rate);
if (aac->cfg.channels < 1 || aac->cfg.channels > 2) {
pr_err("[%s:%s]invalid number of channels\n",
__MM_FILE__, __func__);
rc = -EINVAL;
}
if (aac->cfg.sample_rate != 48000) {
pr_err("[%s:%s] only 48KHz is supported\n",
__MM_FILE__, __func__);
rc = -EINVAL;
}
if (aac->cfg.stream_format != AUDIO_AAC_FORMAT_RAW &&
aac->cfg.stream_format != AUDIO_AAC_FORMAT_ADTS) {
pr_err("[%s:%s] unsupported AAC format\n", __MM_FILE__,
__func__);
rc = -EINVAL;
}
break;
case AUDIO_GET_AAC_ENC_CONFIG:
if (copy_to_user((void *) arg, &aac->cfg,
sizeof(struct msm_audio_aac_enc_config))) {
rc = -EFAULT;
}
pr_debug("[%s:%s] GET_AAC_ENC_CONFIG: channels=%d, rate=%d\n",
__MM_FILE__, __func__, aac->cfg.channels,
aac->cfg.sample_rate);
break;
default:
rc = -EINVAL;
}
mutex_unlock(&aac->lock);
pr_debug("[%s:%s] rc = %d\n", __MM_FILE__, __func__, rc);
return rc;
}
static int q6_aac_in_open(struct inode *inode, struct file *file)
{
struct aac *aac;
struct aac_fc *fc;
int i;
pr_info("[%s:%s] open\n", __MM_FILE__, __func__);
aac = kmalloc(sizeof(struct aac), GFP_KERNEL);
if (aac == NULL) {
pr_err("[%s:%s] Could not allocate memory for aac driver\n",
__MM_FILE__, __func__);
return -ENOMEM;
}
mutex_init(&aac->lock);
file->private_data = aac;
aac->audio_client = NULL;
aac->str_cfg.buffer_size = 1543;
aac->str_cfg.buffer_count = 2;
aac->cfg.channels = 1;
aac->cfg.bit_rate = 192000;
aac->cfg.stream_format = AUDIO_AAC_FORMAT_ADTS;
aac->cfg.sample_rate = 48000;
aac->voicerec_mode.rec_mode = AUDIO_FLAG_READ;
aac->aac_fc = kmalloc(sizeof(struct aac_fc), GFP_KERNEL);
if (aac->aac_fc == NULL) {
pr_err("[%s:%s] Could not allocate memory for aac_fc\n",
__MM_FILE__, __func__);
kfree(aac);
return -ENOMEM;
}
fc = aac->aac_fc;
fc->task = NULL;
fc->buff_index = 0;
for (i = 0; i < AAC_FC_BUFF_CNT; ++i) {
fc->fc_buff[i].data = NULL;
fc->fc_buff[i].size = 0;
fc->fc_buff[i].actual_size = 0;
}
/*initialize wait queue head*/
init_waitqueue_head(&fc->fc_wq);
return 0;
}
static ssize_t q6_aac_in_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
struct audio_client *ac;
const char __user *start = buf;
struct aac *aac = file->private_data;
struct aac_fc *fc;
int xfer = 0;
int res = 0;
pr_debug("[%s:%s] count = %d\n", __MM_FILE__, __func__, count);
mutex_lock(&aac->lock);
ac = aac->audio_client;
mutex_lock(&aac_in_lock);
ac = file->private_data;
if (!ac) {
res = -ENODEV;
goto fail;
}
while (count > 0) {
ab = ac->buf + ac->cpu_buf;
fc = aac->aac_fc;
if (ab->used)
if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
audio_client_dump(ac);
pr_err("aac_read: timeout. dsp dead?\n");
BUG();
}
/*wait for buffer to full*/
if (fc->fc_buff[fc->buff_index].empty != 0) {
res = wait_event_interruptible_timeout(fc->fc_wq,
(fc->fc_buff[fc->buff_index].empty == 0),
msecs_to_jiffies(AAC_READ_TIMEOUT));
xfer = count;
if (xfer > ab->size)
xfer = ab->size;
if (copy_to_user(buf, ab->data, xfer)) {
res = -EFAULT;
pr_debug("[%s:%s] buff_index = %d\n", __MM_FILE__,
__func__, fc->buff_index);
if (res == 0) {
pr_err("[%s:%s] Timeout!\n", __MM_FILE__, __func__);
res = -ETIMEDOUT;
goto fail;
} else if (res < 0) {
pr_err("[%s:%s] Returning on Interrupt\n", __MM_FILE__,
__func__);
goto fail;
}
buf += xfer;
count -= xfer;
ab->used = 1;
q6audio_read(ac, ab);
ac->cpu_buf ^= 1;
}
fail:
/*lock the buffer*/
mutex_lock(&(fc->fc_buff[fc->buff_index].lock));
xfer = fc->fc_buff[fc->buff_index].actual_size;
if (xfer > count) {
mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
pr_err("[%s:%s] read failed! byte count too small\n",
__MM_FILE__, __func__);
res = -EINVAL;
goto fail;
}
if (copy_to_user(buf, fc->fc_buff[fc->buff_index].data, xfer)) {
mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
pr_err("[%s:%s] copy_to_user failed at index %d\n",
__MM_FILE__, __func__, fc->buff_index);
res = -EFAULT;
goto fail;
}
buf += xfer;
fc->fc_buff[fc->buff_index].empty = 1;
fc->fc_buff[fc->buff_index].actual_size = 0;
mutex_unlock(&(fc->fc_buff[fc->buff_index].lock));
++(fc->buff_index);
if (fc->buff_index >= AAC_FC_BUFF_CNT)
fc->buff_index = 0;
res = buf - start;
mutex_unlock(&aac_in_lock);
fail:
mutex_unlock(&aac->lock);
return res;
}
static int aac_in_release(struct inode *inode, struct file *file)
static int q6_aac_in_release(struct inode *inode, struct file *file)
{
int rc = 0;
pr_info("aac_in: release\n");
mutex_lock(&aac_in_lock);
if (file->private_data)
rc = q6audio_close(file->private_data);
kfree(af);
aac_in_opened = 0;
mutex_unlock(&aac_in_lock);
struct aac *aac = file->private_data;
int i = 0;
struct aac_fc *fc;
mutex_lock(&aac->lock);
fc = aac->aac_fc;
kthread_stop(fc->task);
fc->task = NULL;
/*free flow control buffers*/
for (i = 0; i < AAC_FC_BUFF_CNT; ++i) {
kfree(fc->fc_buff[i].data);
fc->fc_buff[i].data = NULL;
}
kfree(fc);
if (aac->audio_client)
rc = q6audio_close(aac->audio_client);
mutex_unlock(&aac->lock);
kfree(aac);
pr_info("[%s:%s] release\n", __MM_FILE__, __func__);
return rc;
}
static struct file_operations aac_in_fops = {
.owner = THIS_MODULE,
.open = aac_in_open,
.read = aac_in_read,
.release = aac_in_release,
.unlocked_ioctl = aac_in_ioctl,
static const struct file_operations q6_aac_in_fops = {
.owner = THIS_MODULE,
.open = q6_aac_in_open,
.read = q6_aac_in_read,
.release = q6_aac_in_release,
.unlocked_ioctl = q6_aac_in_ioctl,
};
struct miscdevice aac_in_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "msm_aac_in",
.fops = &aac_in_fops,
struct miscdevice q6_aac_in_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "msm_aac_in",
.fops = &q6_aac_in_fops,
};
static int __init aac_in_init(void) {
return misc_register(&aac_in_misc);
static int __init q6_aac_in_init(void)
{
return misc_register(&q6_aac_in_misc);
}
device_initcall(aac_in_init);
device_initcall(q6_aac_in_init);

View File

@ -18,7 +18,7 @@
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/msm_audio.h>
#include <linux/msm_audio_1550.h>
#include <mach/msm_qdsp6_audio_1550.h>
#include <mach/htc_acoustic_qsd.h>
@ -133,8 +133,7 @@ static int q6_open(struct inode *inode, struct file *file)
return 0;
}
static int q6_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long q6_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int rc;
uint32_t n;
@ -147,28 +146,40 @@ static int q6_ioctl(struct inode *inode, struct file *file,
case AUDIO_SWITCH_DEVICE:
rc = copy_from_user(&id, (void *)arg, sizeof(id));
AUDIO_INFO("SWITCH DEVICE %d, acdb %d\n", id[0], id[1]);
if (!rc)
if (rc) {
pr_err("%s: bad user address\n", __func__);
rc = -EFAULT;
} else
rc = q6audio_do_routing(id[0], id[1]);
break;
case AUDIO_SET_VOLUME:
rc = copy_from_user(&n, (void *)arg, sizeof(n));
if (!rc)
if (rc) {
pr_err("%s: bad user address\n", __func__);
rc = -EFAULT;
} else
rc = q6audio_set_rx_volume(n);
break;
case AUDIO_SET_MUTE:
rc = copy_from_user(&n, (void *)arg, sizeof(n));
if (!rc)
if (rc) {
pr_err("%s: bad user address\n", __func__);
rc = -EFAULT;
} else
rc = q6audio_set_tx_mute(n);
break;
case AUDIO_UPDATE_ACDB:
rc = copy_from_user(&id, (void *)arg, sizeof(id));
if (!rc)
if (rc) {
pr_err("%s: bad user address\n", __func__);
rc = -EFAULT;
} else
rc = q6audio_update_acdb(id[0], id[1]);
break;
case AUDIO_START_VOICE:
if (arg == 0) {
if (arg == 0)
id[0] = id[1] = 0;
} else if (copy_from_user(&id, (void*) arg, sizeof(id))) {
else if (copy_from_user(&id, (void*) arg, sizeof(id))) {
pr_info("voice: copy acdb_id from user failed\n");
rc = -EFAULT;
break;

View File

@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/errno.h>

View File

@ -19,6 +19,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/uaccess.h>

View File

@ -41,6 +41,7 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/wakelock.h>

View File

@ -42,6 +42,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/android_pmem.h>
@ -358,7 +359,7 @@ static int q6_encode(struct q6venc_dev *q6venc, struct encode_param *enc_param)
{
struct q6_encode_param *q6_param = &enc_param->q6_encode_param;
struct file *file;
struct buf_info *buf;
struct buf_info *buf = 0;
int i;
int ret;
int rlc_buf_index;

View File

@ -14,6 +14,7 @@
*
*/
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/miscdevice.h>

View File

@ -19,6 +19,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
@ -64,6 +65,12 @@ static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) {
case AUDIO_SET_VOLUME: {
int vol;
if (!pcm->ac) {
pr_err("%s: cannot set volume before AUDIO_START!\n",
__func__);
rc = -EINVAL;
break;
}
if (copy_from_user(&vol, (void*) arg, sizeof(vol))) {
rc = -EFAULT;
break;

View File

@ -17,6 +17,7 @@
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
@ -32,11 +33,12 @@
#include "dal_acdb.h"
#include "dal_adie.h"
#include <mach/msm_qdsp6_audio_1550.h>
#include <linux/msm_audio.h>
#include <linux/msm_audio_1550.h>
#include <mach/htc_acoustic_qsd.h>
#include <mach/msm_audio_qcp.h>
#include <linux/gpio.h>
#include <linux/msm_audio_aac.h>
#include "q6audio_devices.h"
#include "../dex_comm.h"
@ -172,7 +174,7 @@ static struct audio_client * audio_test(void);
static void callback(void *data, int len, void *cookie);
static int audio_init(struct audio_client *ac);
static int audio_info(struct audio_client *ac);
static int q6audio_init_rx_volumes();
static int q6audio_init_rx_volumes(void);
static struct wake_lock wakelock;
static struct wake_lock idlelock;
@ -215,6 +217,7 @@ static char acdb_file[64] = "default.acdb";
static uint32_t tx_acdb = 0;
static uint32_t rx_acdb = 0;
static int acdb_use_rpc = 0;
static int acdb_use_map = 0;
/////////////////////////////////////////////////////////////////////////////////
// helper functions for device parameters
@ -699,10 +702,18 @@ static int audio_mp3_open(struct audio_client *ac, uint32_t bufsz,
return ac->open_status;
}
static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
/*
* ported code for audio_aac_open from Code Aurora in order to work
* with new aac code from Code Aurora
* by marc1706
*/
static int audio_aac_open(struct audio_client *ac, uint32_t bufsz,
uint32_t sample_rate, uint32_t channels,
uint32_t bit_rate, uint32_t flags,
uint32_t stream_format)
{
int r;
struct aac_format *af = data;
int audio_object_type;
struct adsp_open_command rpc;
uint32_t *aac_type;
int idx = 0; // sizeof(uint32_t);
@ -723,77 +734,33 @@ static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
rpc.pblock = params_phys;
aac_type = (uint32_t *)(fmt->data);
switch (af->block_formats)
switch (stream_format)
{
case 0xffff:
if (ac->flags & AUDIO_FLAG_WRITE)
*aac_type = ADSP_AUDIO_AAC_ADTS;
else
*aac_type = ADSP_AUDIO_AAC_MPEG4_ADTS;
break;
case 0:
if (ac->flags & AUDIO_FLAG_WRITE)
*aac_type = ADSP_AUDIO_AAC_ADIF;
else
*aac_type = ADSP_AUDIO_AAC_RAW;
break;
case 1:
*aac_type = ADSP_AUDIO_AAC_RAW;
break;
case 2:
*aac_type = ADSP_AUDIO_AAC_LOAS;
break;
case 3:
*aac_type = ADSP_AUDIO_AAC_FRAMED_RAW;
break;
case 4:
*aac_type = ADSP_AUDIO_AAC_RAW;
break;
case AUDIO_AAC_FORMAT_ADTS:
/* AAC Encoder expect MPEG4_ADTS media type */
*aac_type = ADSP_AUDIO_AAC_MPEG4_ADTS;
break;
case AUDIO_AAC_FORMAT_RAW:
/* for ADIF recording */
*aac_type = ADSP_AUDIO_AAC_RAW;
break;
default:
pr_err("unsupported AAC type %d\n", af->block_formats);
pr_err("unsupported AAC type %d\n", stream_format);
mutex_unlock(&open_mem_lock);
return -EINVAL;
}
/* AAC OBJECT LC */
audio_object_type = 2;
AUDIO_INFO("aac_open: type %x, obj %d, idx %d\n",
*aac_type, af->audio_object_type, idx);
fmt->data[idx++] = (u8)(((af->audio_object_type & 0x1F) << 3) |
((af->sample_rate >> 1) & 0x7));
fmt->data[idx] = (u8)(((af->sample_rate & 0x1) << 7) |
((af->channel_config & 0x7) << 3));
*aac_type, audio_object_type, idx);
switch (af->audio_object_type) {
case AAC_OBJECT_ER_LC:
case AAC_OBJECT_ER_LTP:
case AAC_OBJECT_ER_LD:
/* extension flag */
fmt->data[idx++] |= 0x1;
fmt->data[idx] = (u8)(
((af->aac_section_data_resilience_flag & 0x1) << 7) |
((af->aac_scalefactor_data_resilience_flag & 0x1) << 6) |
((af->aac_spectral_data_resilience_flag & 0x1) << 5) |
((af->ep_config & 0x3) << 2));
break;
fmt->data[idx++] = (u8)(((audio_object_type & 0x1F) << 3) |
((sample_rate >> 1) & 0x7));
fmt->data[idx] = (u8)(((sample_rate & 0x1) << 7) |
((channels & 0x7) << 3));
case AAC_OBJECT_ER_SCALABLE:
fmt->data[idx++] |= 0x1;
/* extension flag */
fmt->data[idx++] = (u8)(
((af->aac_section_data_resilience_flag & 0x1) << 4) |
((af->aac_scalefactor_data_resilience_flag & 0x1) << 3) |
((af->aac_spectral_data_resilience_flag & 0x1) << 2) |
((af->ep_config >> 1) & 0x1));
fmt->data[idx] = (u8)((af->ep_config & 0x1) << 7);
break;
case AAC_OBJECT_BSAC:
fmt->data[++idx] = (u8)((af->ep_config & 0x3) << 6);
break;
default:
pr_err("dbg unknown object type \n");
break;
}
// fmt->num_bytes = idx + 1;
rpc.blocklen = idx + 1;
@ -801,8 +768,8 @@ static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
fmt->data[0], fmt->data[1], fmt->data[2], fmt->data[3],
fmt->data[4], fmt->data[5], fmt->data[6], fmt->data[7]);
rpc.config.aac.bit_rate = af->bit_rate;
if (ac->flags & AUDIO_FLAG_WRITE)
rpc.config.aac.bit_rate = bit_rate;
if (flags & AUDIO_FLAG_WRITE)
{
rpc.opcode = ADSP_AUDIO_OPCODE_OPEN_WRITE;
rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_PLAYBACK;
@ -813,25 +780,13 @@ static int audio_aac_open(struct audio_client *ac, uint32_t bufsz, void *data)
rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_RECORD;
}
if ((af->sbr_on_flag == 0) && (af->sbr_ps_on_flag == 0))
{
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_AAC_LC_ONLY_MODE;
}
else if ((af->sbr_on_flag == 1) && (af->sbr_ps_on_flag == 0))
{
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_AAC_PLUS_MODE;
}
else if ((af->sbr_on_flag == 1) && (af->sbr_ps_on_flag == 1))
{
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_ENHANCED_AAC_PLUS_MODE;
}
else
{
pr_err("unsupported SBR flag\n");
mutex_unlock(&open_mem_lock);
return -EINVAL;
}
rpc.buf_max_size = bufsz; /* XXX ??? */
/*
* Always use ADSP_AUDIO_ENC_AAC_LC_ONLY_MODE as encoder_mode
* from Code Aurora
* by marc1706
*/
rpc.config.aac.encoder_mode = ADSP_AUDIO_ENC_AAC_LC_ONLY_MODE;
rpc.buf_max_size = bufsz;
TRACE("aac_open: opcode %x, stream_context 0x%x, "
"mode %d, bytes %d, bbuffer size %d\n",
@ -1233,11 +1188,29 @@ static int acdb_init(char *filename)
const struct firmware *fw;
int n;
// return -ENODEV;
AUDIO_INFO("%s\n", __func__);
#ifdef CONFIG_MACH_HTCLEO
pr_info("acdb: trying htcleo.acdb\n");
if(request_firmware(&fw, "htcleo.acdb", q6_control_device.this_device) < 0) {
pr_info("acdb: load 'htcleo.acdb' failed, trying 'default.acdb'\n");
acdb_use_map = 0;
if (request_firmware(&fw, filename, q6_control_device.this_device) < 0) {
pr_err("acdb: load 'default.acdb' failed...\n");
return -ENODEV;
}
} else {
pr_info("acdb: 'htcleo.acdb' found, using translation\n");
acdb_use_map = 1;
}
#else
pr_info("acdb: load '%s'\n", filename);
acd_use_map = 0;
if (request_firmware(&fw, filename, q6_control_device.this_device) < 0) {
pr_err("acdb: load 'default.acdb' failed...\n");
return -ENODEV;
}
#endif
db = (void*) fw->data;
if (fw->size < sizeof(struct audio_config_database)) {
@ -1448,6 +1421,9 @@ static int acdb_get_config_table(uint32_t device_id, uint32_t sample_rate)
int n;
printk("table\n");
// htcleo use custom table with wince values, it must be mapped
if(acdb_use_map)
device_id = map_cad_dev_to_virtual(device_id);
db = acdb_data;
for (n = 0; n < db->entry_count; n++)
{
@ -2209,7 +2185,7 @@ int q6audio_set_rx_volume(int level)
}
EXPORT_SYMBOL_GPL(q6audio_set_rx_volume);
static int q6audio_init_rx_volumes()
static int q6audio_init_rx_volumes(void)
{
int vol;
struct q6_device_info *di = q6_audio_devices;
@ -2628,14 +2604,19 @@ int q6audio_async(struct audio_client *ac)
}
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate,
uint32_t flags, void *data, uint32_t acdb_id)
/*
* ported code for q6audio_open_aac from Code Aurora
* by marc1706
*/
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t samplerate,
uint32_t channels, uint32_t bitrate,
uint32_t stream_format, uint32_t flags,
uint32_t acdb_id)
{
struct audio_client *ac;
AUDIO_INFO("%s\n", __func__);
TRACE("q6audio_open_aac flags=%d rate=%d\n", flags, rate);
TRACE("q6audio_open_aac flags=%d samplerate=%d, channels = %d\n", flags, samplerate, channels);
if (q6audio_init())
return 0;
@ -2648,12 +2629,13 @@ struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate,
if (ac->flags & AUDIO_FLAG_WRITE)
audio_rx_path_enable(1, acdb_id);
else {
/* TODO: consider concourrency with voice call */
tx_clk_freq = rate;
if (!audio_tx_path_refcount)
tx_clk_freq = 48000;
audio_tx_path_enable(1, acdb_id);
}
audio_aac_open(ac, bufsz, data);
audio_aac_open(ac, bufsz, samplerate, channels, bitrate, flags,
stream_format);
audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START);
if (!(ac->flags & AUDIO_FLAG_WRITE)) {

View File

@ -19,6 +19,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/msm_audio.h>

View File

@ -188,6 +188,12 @@ static void sirc_irq_handler(unsigned int irq, struct irq_desc *desc)
(sirc_reg_table[reg].cascade_irq != irq))
reg++;
if (reg == ARRAY_SIZE(sirc_reg_table)) {
printk(KERN_ERR "%s: incorrect irq %d called\n",
__func__, irq);
return;
}
status = readl(sirc_reg_table[reg].int_status);
status &= SIRC_MASK;
if (status == 0)

View File

@ -381,17 +381,18 @@ static void update_packet_state(struct smd_channel *ch)
int r;
/* can't do anything if we're in the middle of a packet */
if (ch->current_packet != 0)
return;
while (ch->current_packet == 0) {
/* discard 0 length packets if any */
/* don't bother unless we can get the full header */
if (smd_stream_read_avail(ch) < SMD_HEADER_SIZE)
return;
/* don't bother unless we can get the full header */
if (smd_stream_read_avail(ch) < SMD_HEADER_SIZE)
return;
r = ch_read(ch, hdr, SMD_HEADER_SIZE);
BUG_ON(r != SMD_HEADER_SIZE);
r = ch_read(ch, hdr, SMD_HEADER_SIZE);
BUG_ON(r != SMD_HEADER_SIZE);
ch->current_packet = hdr[0];
ch->current_packet = hdr[0];
}
}
/* provide a pointer and length to next free space in the fifo */
@ -490,7 +491,7 @@ static void handle_smd_irq(struct list_head *list, void (*notify)(void))
#ifdef CONFIG_BUILD_CIQ
/* put here to make sure we got the disable/enable index */
if (!msm_smd_ciq_info)
msm_smd_ciq_info = (*(volatile uint32_t *)(MSM_SHARED_RAM_BASE + 0xFC11C));
msm_smd_ciq_info = (*(volatile uint32_t *)(MSM_SHARED_RAM_BASE + SMD_CIQ_BASE));
#endif
spin_lock_irqsave(&smd_lock, flags);
list_for_each_entry(ch, list, ch_list) {
@ -641,6 +642,8 @@ static int smd_stream_write(smd_channel_t *ch, const void *_data, int len)
if (len < 0)
return -EINVAL;
else if (len == 0)
return 0;
while ((xfer = ch_write_buffer(ch, &ptr)) != 0) {
if (!ch_is_open(ch))
@ -911,6 +914,7 @@ int smd_close(smd_channel_t *ch)
return 0;
}
EXPORT_SYMBOL(smd_close);
int smd_read(smd_channel_t *ch, void *data, int len)
{
@ -922,6 +926,7 @@ int smd_write(smd_channel_t *ch, const void *data, int len)
{
return ch->write(ch, data, len);
}
EXPORT_SYMBOL(smd_write);
int smd_write_atomic(smd_channel_t *ch, const void *data, int len)
{
@ -944,6 +949,7 @@ int smd_write_avail(smd_channel_t *ch)
{
return ch->write_avail(ch);
}
EXPORT_SYMBOL_GPL(smd_write_avail);
int smd_wait_until_readable(smd_channel_t *ch, int bytes)
{
@ -981,6 +987,11 @@ int smd_cur_packet_size(smd_channel_t *ch)
}
EXPORT_SYMBOL(smd_cur_packet_size);
/* Returns SMD buffer size */
int smd_total_fifo_size(smd_channel_t *ch)
{
return ch->fifo_size;
}
/* ------------------------------------------------------------------------- */

View File

@ -89,6 +89,33 @@ struct smsm_interrupt_info {
};
#endif
#if defined(CONFIG_MSM_N_WAY_SMSM)
enum {
SMSM_APPS_STATE,
SMSM_MODEM_STATE,
SMSM_Q6_STATE,
SMSM_APPS_DEM,
SMSM_MODEM_DEM,
SMSM_Q6_DEM,
SMSM_POWER_MASTER_DEM,
SMSM_TIME_MASTER_DEM,
SMSM_NUM_ENTRIES,
};
#else
enum {
SMSM_APPS_STATE = 1,
SMSM_MODEM_STATE = 3,
SMSM_NUM_ENTRIES,
};
#endif
enum {
SMSM_APPS,
SMSM_MODEM,
SMSM_Q6,
SMSM_NUM_HOSTS,
};
#define SZ_DIAG_ERR_MSG 0xC8
#define ID_DIAG_ERR_MSG SMEM_DIAG_ERR_MESSAGE
#define ID_SMD_CHANNELS SMEM_SMD_BASE_ID

View File

@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/cdev.h>
@ -105,7 +106,7 @@ static struct wake_lock rpcrouter_wake_lock;
static int rpcrouter_need_len;
static atomic_t next_xid = ATOMIC_INIT(1);
static uint8_t next_pacmarkid;
static atomic_t next_mid = ATOMIC_INIT(0);
static void do_read_data(struct work_struct *work);
static void do_create_pdevs(struct work_struct *work);
@ -114,12 +115,16 @@ static void do_create_rpcrouter_pdev(struct work_struct *work);
static DECLARE_WORK(work_read_data, do_read_data);
static DECLARE_WORK(work_create_pdevs, do_create_pdevs);
static DECLARE_WORK(work_create_rpcrouter_pdev, do_create_rpcrouter_pdev);
static atomic_t rpcrouter_pdev_created = ATOMIC_INIT(0);
#define RR_STATE_IDLE 0
#define RR_STATE_HEADER 1
#define RR_STATE_BODY 2
#define RR_STATE_ERROR 3
#define RMT_STORAGE_APIPROG_BE32 0xa7000030
#define RMT_STORAGE_SRV_APIPROG_BE32 0x9c000030
struct rr_context {
struct rr_packet *pkt;
uint8_t *ptr;
@ -262,6 +267,7 @@ struct msm_rpc_endpoint *msm_rpcrouter_create_local_endpoint(dev_t dev)
{
struct msm_rpc_endpoint *ept;
unsigned long flags;
int i;
ept = kmalloc(sizeof(struct msm_rpc_endpoint), GFP_KERNEL);
if (!ept)
@ -269,7 +275,9 @@ struct msm_rpc_endpoint *msm_rpcrouter_create_local_endpoint(dev_t dev)
memset(ept, 0, sizeof(struct msm_rpc_endpoint));
/* mark no reply outstanding */
ept->reply_pid = 0xffffffff;
ept->next_rroute = 0;
for (i = 0; i < MAX_REPLY_ROUTE; i++)
ept->rroute[i].pid = 0xffffffff;
ept->cid = (uint32_t) ept;
ept->pid = RPCROUTER_PID_LOCAL;
@ -530,7 +538,8 @@ static int process_control_msg(union rr_control_msg *msg, int len)
static void do_create_rpcrouter_pdev(struct work_struct *work)
{
platform_device_register(&rpcrouter_pdev);
if (atomic_cmpxchg(&rpcrouter_pdev_created, 0, 1) == 0)
platform_device_register(&rpcrouter_pdev);
}
static void do_create_pdevs(struct work_struct *work)
@ -652,11 +661,13 @@ static void do_read_data(struct work_struct *work)
hdr.size -= sizeof(pm);
frag = rr_malloc(hdr.size + sizeof(*frag));
frag = rr_malloc(sizeof(*frag));
frag->next = NULL;
frag->length = hdr.size;
if (rr_read(frag->data, hdr.size))
if (rr_read(frag->data, hdr.size)) {
kfree(frag);
goto fail_io;
}
ept = rpcrouter_lookup_local_endpoint(hdr.dst_cid);
if (!ept) {
@ -758,19 +769,77 @@ int msm_rpc_close(struct msm_rpc_endpoint *ept)
}
EXPORT_SYMBOL(msm_rpc_close);
static int msm_rpc_write_pkt(struct msm_rpc_endpoint *ept,
struct rr_remote_endpoint *r_ept,
struct rr_header *hdr,
uint32_t pacmark,
void *buffer, int count)
{
DEFINE_WAIT(__wait);
unsigned long flags;
int needed;
for (;;) {
prepare_to_wait(&r_ept->quota_wait, &__wait,
TASK_INTERRUPTIBLE);
spin_lock_irqsave(&r_ept->quota_lock, flags);
if (r_ept->tx_quota_cntr < RPCROUTER_DEFAULT_RX_QUOTA)
break;
if (signal_pending(current) &&
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE)))
break;
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
schedule();
}
finish_wait(&r_ept->quota_wait, &__wait);
if (signal_pending(current) &&
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE))) {
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
return -ERESTARTSYS;
}
r_ept->tx_quota_cntr++;
if (r_ept->tx_quota_cntr == RPCROUTER_DEFAULT_RX_QUOTA)
hdr->confirm_rx = 1;
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
spin_lock_irqsave(&smd_lock, flags);
needed = sizeof(*hdr) + hdr->size;
while (smd_write_avail(smd_channel) < needed) {
spin_unlock_irqrestore(&smd_lock, flags);
msleep(250);
spin_lock_irqsave(&smd_lock, flags);
}
/* TODO: deal with full fifo */
smd_write(smd_channel, hdr, sizeof(*hdr));
smd_write(smd_channel, &pacmark, sizeof(pacmark));
smd_write(smd_channel, buffer, count);
spin_unlock_irqrestore(&smd_lock, flags);
return 0;
}
int msm_rpc_write(struct msm_rpc_endpoint *ept, void *buffer, int count)
{
struct rr_header hdr;
uint32_t pacmark;
uint32_t mid;
struct rpc_request_hdr *rq = buffer;
struct rr_remote_endpoint *r_ept;
unsigned long flags;
int needed;
DEFINE_WAIT(__wait);
int ret;
int total;
/* TODO: fragmentation for large outbound packets */
if (count > (RPCROUTER_MSGSIZE_MAX - sizeof(uint32_t)) || !count)
return -EINVAL;
if (((rq->prog&0xFFFFFFF0) == RMT_STORAGE_APIPROG_BE32) ||
((rq->prog&0xFFFFFFF0) == RMT_STORAGE_SRV_APIPROG_BE32)) {
printk(KERN_DEBUG
"rpc_write: prog = %x , procedure = %d, type = %d, xid = %d\n"
, be32_to_cpu(rq->prog), be32_to_cpu(rq->procedure)
, be32_to_cpu(rq->type), be32_to_cpu(rq->xid));
}
/* snoop the RPC packet and enforce permissions */
@ -818,23 +887,21 @@ int msm_rpc_write(struct msm_rpc_endpoint *ept, void *buffer, int count)
} else {
/* RPC REPLY */
/* TODO: locking */
if (ept->reply_pid == 0xffffffff) {
printk(KERN_ERR
"rr_write: rejecting unexpected reply\n");
return -EINVAL;
}
if (ept->reply_xid != rq->xid) {
printk(KERN_ERR
"rr_write: rejecting packet w/ bad xid\n");
return -EINVAL;
for (ret = 0; ret < MAX_REPLY_ROUTE; ret++)
if (ept->rroute[ret].xid == rq->xid) {
if (ept->rroute[ret].pid == 0xffffffff)
continue;
hdr.dst_pid = ept->rroute[ret].pid;
hdr.dst_cid = ept->rroute[ret].cid;
/* consume this reply */
ept->rroute[ret].pid = 0xffffffff;
goto found_rroute;
}
hdr.dst_pid = ept->reply_pid;
hdr.dst_cid = ept->reply_cid;
/* consume this reply */
ept->reply_pid = 0xffffffff;
printk(KERN_ERR "rr_write: rejecting packet w/ bad xid\n");
return -EINVAL;
found_rroute:
IO("REPLY on ept %p to xid=%d @ %d:%08x (%d bytes)\n",
ept,
be32_to_cpu(rq->xid), hdr.dst_pid, hdr.dst_cid, count);
@ -854,56 +921,36 @@ int msm_rpc_write(struct msm_rpc_endpoint *ept, void *buffer, int count)
hdr.version = RPCROUTER_VERSION;
hdr.src_pid = ept->pid;
hdr.src_cid = ept->cid;
hdr.confirm_rx = 0;
hdr.size = count + sizeof(uint32_t);
for (;;) {
prepare_to_wait(&r_ept->quota_wait, &__wait,
TASK_INTERRUPTIBLE);
spin_lock_irqsave(&r_ept->quota_lock, flags);
if (r_ept->tx_quota_cntr < RPCROUTER_DEFAULT_RX_QUOTA)
break;
if (signal_pending(current) &&
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE)))
break;
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
schedule();
}
finish_wait(&r_ept->quota_wait, &__wait);
total = count;
if (signal_pending(current) &&
(!(ept->flags & MSM_RPC_UNINTERRUPTIBLE))) {
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
return -ERESTARTSYS;
}
r_ept->tx_quota_cntr++;
if (r_ept->tx_quota_cntr == RPCROUTER_DEFAULT_RX_QUOTA)
hdr.confirm_rx = 1;
mid = atomic_add_return(1, &next_mid) & 0xFF;
/* bump pacmark while interrupts disabled to avoid race
* probably should be atomic op instead
*/
pacmark = PACMARK(count, ++next_pacmarkid, 0, 1);
while (count > 0) {
unsigned xfer;
spin_unlock_irqrestore(&r_ept->quota_lock, flags);
if (count > RPCROUTER_DATASIZE_MAX)
xfer = RPCROUTER_DATASIZE_MAX;
else
xfer = count;
spin_lock_irqsave(&smd_lock, flags);
hdr.confirm_rx = 0;
hdr.size = xfer + sizeof(uint32_t);
needed = sizeof(hdr) + hdr.size;
while (smd_write_avail(smd_channel) < needed) {
spin_unlock_irqrestore(&smd_lock, flags);
msleep(250);
spin_lock_irqsave(&smd_lock, flags);
/* total == count -> must be first packet
* xfer == count -> must be last packet
*/
pacmark = PACMARK(xfer, mid, (total == count), (xfer == count));
ret = msm_rpc_write_pkt(ept, r_ept, &hdr, pacmark, buffer, xfer);
if (ret < 0)
return ret;
buffer += xfer;
count -= xfer;
}
/* TODO: deal with full fifo */
smd_write(smd_channel, &hdr, sizeof(hdr));
smd_write(smd_channel, &pacmark, sizeof(pacmark));
smd_write(smd_channel, buffer, count);
spin_unlock_irqrestore(&smd_lock, flags);
return count;
return total;
}
EXPORT_SYMBOL(msm_rpc_write);
@ -1104,20 +1151,30 @@ int __msm_rpc_read(struct msm_rpc_endpoint *ept,
*frag_ret = pkt->first;
rq = (void*) pkt->first->data;
if (((rq->prog&0xFFFFFFF0) == RMT_STORAGE_APIPROG_BE32) ||
((rq->prog&0xFFFFFFF0) == RMT_STORAGE_SRV_APIPROG_BE32)) {
printk(KERN_DEBUG
"rpc_read: prog = %x , procedure = %d, type = %d, xid = %d\n"
, be32_to_cpu(rq->prog), be32_to_cpu(rq->procedure)
, be32_to_cpu(rq->type), be32_to_cpu(rq->xid));
}
if ((rc >= (sizeof(uint32_t) * 3)) && (rq->type == 0)) {
IO("READ on ept %p is a CALL on %08x:%08x proc %d xid %d\n",
ept, be32_to_cpu(rq->prog), be32_to_cpu(rq->vers),
be32_to_cpu(rq->procedure),
be32_to_cpu(rq->xid));
/* RPC CALL */
if (ept->reply_pid != 0xffffffff) {
if (ept->rroute[ept->next_rroute].pid != 0xffffffff) {
printk(KERN_WARNING
"rr_read: lost previous reply xid...\n");
}
/* TODO: locking? */
ept->reply_pid = pkt->hdr.src_pid;
ept->reply_cid = pkt->hdr.src_cid;
ept->reply_xid = rq->xid;
ept->rroute[ept->next_rroute].pid = pkt->hdr.src_pid;
ept->rroute[ept->next_rroute].cid = pkt->hdr.src_cid;
ept->rroute[ept->next_rroute].xid = rq->xid;
ept->next_rroute = (ept->next_rroute + 1) & (MAX_REPLY_ROUTE - 1);
}
#if TRACE_RPC_MSG
else if ((rc >= (sizeof(uint32_t) * 3)) && (rq->type == 1))

View File

@ -32,6 +32,7 @@
#define RPCROUTER_VERSION 1
#define RPCROUTER_PROCESSORS_MAX 4
#define RPCROUTER_MSGSIZE_MAX 512
#define RPCROUTER_DATASIZE_MAX 500
#if defined(CONFIG_ARCH_MSM7X30)
#define RPCROUTER_PEND_REPLIES_MAX 32
#endif
@ -50,6 +51,7 @@
#define RPCROUTER_CTRL_CMD_REMOVE_CLIENT 6
#define RPCROUTER_CTRL_CMD_RESUME_TX 7
#define RPCROUTER_CTRL_CMD_EXIT 8
#define RPCROUTER_CTRL_CMD_PING 9
#define RPCROUTER_DEFAULT_RX_QUOTA 5
@ -141,6 +143,15 @@ struct rr_remote_endpoint {
struct list_head list;
};
struct msm_reply_route {
uint32_t xid;
uint32_t pid;
uint32_t cid;
uint32_t unused;
};
#define MAX_REPLY_ROUTE 4
#if defined(CONFIG_ARCH_MSM7X30)
struct msm_rpc_reply {
struct list_head list;
@ -183,15 +194,12 @@ struct msm_rpc_endpoint {
uint32_t dst_prog; /* be32 */
uint32_t dst_vers; /* be32 */
/* reply remote address
* if reply_pid == 0xffffffff, none available
* RPC_REPLY writes may only go to the pid/cid/xid of the
* last RPC_CALL we received.
/* RPC_REPLY writes must be routed to the pid/cid of the
* RPC_CALL they are in reply to. Keep a cache of valid
* xid/pid/cid groups. pid 0xffffffff -> not valid.
*/
uint32_t reply_pid;
uint32_t reply_cid;
uint32_t reply_xid; /* be32 */
uint32_t next_pm; /* Pacmark sequence */
unsigned next_rroute;
struct msm_reply_route rroute[MAX_REPLY_ROUTE];
#if defined(CONFIG_ARCH_MSM7X30)
/* reply queue for inbound messages */
@ -224,6 +232,7 @@ void msm_rpcrouter_exit_devices(void);
#if defined(CONFIG_ARCH_MSM7X30)
void get_requesting_client(struct msm_rpc_endpoint *ept, uint32_t xid,
struct msm_rpc_client_info *clnt_info);
int msm_rpc_clear_netreset(struct msm_rpc_endpoint *ept);
#endif
extern dev_t msm_rpcrouter_devno;

View File

@ -26,6 +26,7 @@
#include <linux/fs.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/platform_device.h>
#include <linux/msm_rpcrouter.h>

View File

@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/cdev.h>

View File

@ -78,6 +78,8 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <mach/msm_rpcrouter.h>
@ -421,7 +423,7 @@ int xdr_send_msg(struct msm_rpc_xdr *xdr)
void xdr_init(struct msm_rpc_xdr *xdr)
{
mutex_init(&xdr->out_lock);
mutex_init(&xdr->in_lock);
init_waitqueue_head(&xdr->in_buf_wait_q);
xdr->in_buf = NULL;
xdr->in_size = 0;
@ -434,7 +436,7 @@ void xdr_init(struct msm_rpc_xdr *xdr)
void xdr_init_input(struct msm_rpc_xdr *xdr, void *buf, uint32_t size)
{
mutex_lock(&xdr->in_lock);
wait_event(xdr->in_buf_wait_q, !(xdr->in_buf));
xdr->in_buf = buf;
xdr->in_size = size;
@ -455,7 +457,7 @@ void xdr_clean_input(struct msm_rpc_xdr *xdr)
xdr->in_size = 0;
xdr->in_index = 0;
mutex_unlock(&xdr->in_lock);
wake_up(&xdr->in_buf_wait_q);
}
void xdr_clean_output(struct msm_rpc_xdr *xdr)

View File

@ -30,6 +30,7 @@
#include "board-htcleo.h"
#define MAX_SMD_TTYS 32
#define MAX_TTY_BUF_SIZE 2048
static DEFINE_MUTEX(smd_tty_lock);
@ -75,6 +76,9 @@ static void smd_tty_work_func(struct work_struct *work)
tty->low_latency = 0;
tty_flip_buffer_push(tty);
break;
if (avail > MAX_TTY_BUF_SIZE)
avail = MAX_TTY_BUF_SIZE;
}
ptr = NULL;

View File

@ -169,18 +169,10 @@ static int msm_timer_set_next_event(unsigned long cycles,
clock->last_set = now;
clock->alarm_vtime = alarm + clock->offset;
late = now - alarm;
if (late >= (int)(-clock->write_delay << clock->shift) && late < DGT_HZ*5) {
static int print_limit = 10;
if (print_limit > 0) {
print_limit--;
printk(KERN_NOTICE "msm_timer_set_next_event(%lu) "
"clock %s, alarm already expired, now %x, "
"alarm %x, late %d%s\n",
cycles, clock->clockevent.name, now, alarm, late,
print_limit ? "" : " stop printing");
}
if (late >= (int)(-clock->write_delay << clock->shift) &&
late < clock->freq*5)
return -ETIME;
}
return 0;
}
@ -582,9 +574,12 @@ static struct msm_clock msm_clocks[] = {
#endif
.freq = GPT_HZ,
.flags =
#ifdef CONFIG_ARCH_MSM_ARM11
MSM_CLOCK_FLAGS_UNSTABLE_COUNT |
MSM_CLOCK_FLAGS_ODD_MATCH_WRITE |
MSM_CLOCK_FLAGS_DELAYED_WRITE_POST,
MSM_CLOCK_FLAGS_DELAYED_WRITE_POST |
#endif
0,
.write_delay = 9,
},
[MSM_CLOCK_DGT] = {

2
drivers/misc/pmem.c Normal file → Executable file
View File

@ -4386,4 +4386,4 @@ static void __exit pmem_exit(void)
module_init(pmem_init);
module_exit(pmem_exit);
#endif
#endif

View File

@ -33,12 +33,15 @@
#include <linux/io.h>
#include <linux/moduleparam.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <asm/dma.h>
#include <asm/mach/flash.h>
#include <mach/dma.h>
unsigned crci_mask;
#if defined(CONFIG_ARCH_MSM7X30)
#define MSM_NAND_BASE 0xA0200000
#else
@ -178,6 +181,11 @@ static void *msm_nand_get_dma_buffer(struct msm_nand_chip *chip, size_t size)
do {
free_index = __ffs(free_bitmask);
current_need_mask = need_mask << free_index;
if (size + free_index * MSM_NAND_DMA_BUFFER_SLOTS >=
MSM_NAND_DMA_BUFFER_SIZE)
return NULL;
if ((bitmask & current_need_mask) == 0) {
old_bitmask =
atomic_cmpxchg(&chip->dma_buffer_busy,
@ -262,7 +270,7 @@ uint32_t flash_read_id(struct msm_nand_chip *chip)
dsb();
msm_dmov_exec_cmd(
chip->dma_channel, DMOV_CMD_PTR_LIST |
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();
@ -306,7 +314,7 @@ int flash_read_config(struct msm_nand_chip *chip)
dsb();
msm_dmov_exec_cmd(
chip->dma_channel, DMOV_CMD_PTR_LIST |
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();
@ -346,7 +354,7 @@ unsigned flash_rd_reg(struct msm_nand_chip *chip, unsigned addr)
dsb();
msm_dmov_exec_cmd(
chip->dma_channel, DMOV_CMD_PTR_LIST |
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();
rv = dma_buffer->data;
@ -379,7 +387,7 @@ void flash_wr_reg(struct msm_nand_chip *chip, unsigned addr, unsigned val)
dsb();
msm_dmov_exec_cmd(
chip->dma_channel, DMOV_CMD_PTR_LIST |
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();
@ -750,7 +758,7 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_o
dsb();
msm_dmov_exec_cmd(
chip->dma_channel, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(
msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();
@ -893,13 +901,13 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_o
dma_buffer->data.result[2].buffer_status,
dma_buffer->data.result[3].flash_status,
dma_buffer->data.result[3].buffer_status,
dma_buffer->data.result[4].flash_status,
dma_buffer->data.result[4].buffer_status,
dma_buffer->data.result[4].buffer_status,
dma_buffer->data.result[5].buffer_status,
dma_buffer->data.result[5].flash_status,
dma_buffer->data.result[5].buffer_status,
dma_buffer->data.result[6].flash_status,
dma_buffer->data.result[6].buffer_status,
dma_buffer->data.result[6].buffer_status,
dma_buffer->data.result[7].buffer_status,
dma_buffer->data.result[7].flash_status,
dma_buffer->data.result[7].buffer_status);
}
#endif
@ -1364,7 +1372,7 @@ msm_nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) | CMD_PTR_LP;
dsb();
msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
msm_dmov_exec_cmd(chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();
/* if any of the writes failed (0x10), or there was a
@ -1576,7 +1584,7 @@ msm_nand_erase(struct mtd_info *mtd, struct erase_info *instr)
dsb();
msm_dmov_exec_cmd(
chip->dma_channel, DMOV_CMD_PTR_LIST |
chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();
@ -1727,7 +1735,7 @@ msm_nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
dma_buffer->cmd) >> 3) | CMD_PTR_LP;
dsb();
msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST |
msm_dmov_exec_cmd(chip->dma_channel, crci_mask, DMOV_CMD_PTR_LIST |
DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr)));
dsb();

View File

@ -697,9 +697,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
u32 *buffer, *dst;
u32 __iomem *src;
int c, i, cnt = 0, err = 0;
u8 *buffer, *dst;
u8 __iomem *src;
int c, cnt = 0, err = 0;
unsigned long total_size;
if (!info || ! info->screen_base)
@ -730,7 +730,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
if (!buffer)
return -ENOMEM;
src = (u32 __iomem *) (info->screen_base + p);
src = (u8 __iomem *) (info->screen_base + p);
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
@ -738,17 +738,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
while (count) {
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
dst = buffer;
for (i = c >> 2; i--; )
*dst++ = fb_readl(src++);
if (c & 3) {
u8 *dst8 = (u8 *) dst;
u8 __iomem *src8 = (u8 __iomem *) src;
for (i = c & 3; i--;)
*dst8++ = fb_readb(src8++);
src = (u32 __iomem *) src8;
}
fb_memcpy_fromfb(dst, src, c);
dst += c;
src += c;
if (copy_to_user(buf, buffer, c)) {
err = -EFAULT;
@ -772,9 +764,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
u32 *buffer, *src;
u32 __iomem *dst;
int c, i, cnt = 0, err = 0;
u8 *buffer, *src;
u8 __iomem *dst;
int c, cnt = 0, err = 0;
unsigned long total_size;
if (!info || !info->screen_base)
@ -811,7 +803,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
if (!buffer)
return -ENOMEM;
dst = (u32 __iomem *) (info->screen_base + p);
dst = (u8 __iomem *) (info->screen_base + p);
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
@ -825,19 +817,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
break;
}
for (i = c >> 2; i--; )
fb_writel(*src++, dst++);
if (c & 3) {
u8 *src8 = (u8 *) src;
u8 __iomem *dst8 = (u8 __iomem *) dst;
for (i = c & 3; i--; )
fb_writeb(*src8++, dst8++);
dst = (u32 __iomem *) dst8;
}
fb_memcpy_tofb(dst, src, c);
dst += c;
src += c;
*ppos += c;
buf += c;
cnt += c;
@ -877,13 +859,13 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
if ((err = info->fbops->fb_pan_display(var, info)))
return err;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
info->var.vmode |= FB_VMODE_YWRAP;
else
info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
info->var.vmode |= FB_VMODE_YWRAP;
else
info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
@ -1438,6 +1420,7 @@ static const struct file_operations fb_fops = {
#ifdef CONFIG_FB_DEFERRED_IO
.fsync = fb_deferred_io_fsync,
#endif
.llseek = default_llseek,
};
struct class *fb_class;
@ -1468,16 +1451,70 @@ static int fb_check_foreignness(struct fb_info *fi)
return 0;
}
static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw)
static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
{
/* is the generic aperture base the same as the HW one */
if (gen->aperture_base == hw->aperture_base)
if (gen->base == hw->base)
return true;
/* is the generic aperture base inside the hw base->hw base+size */
if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size)
if (gen->base > hw->base && gen->base < hw->base + hw->size)
return true;
return false;
}
static bool fb_do_apertures_overlap(struct apertures_struct *gena,
struct apertures_struct *hwa)
{
int i, j;
if (!hwa || !gena)
return false;
for (i = 0; i < hwa->count; ++i) {
struct aperture *h = &hwa->ranges[i];
for (j = 0; j < gena->count; ++j) {
struct aperture *g = &gena->ranges[j];
printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
(unsigned long long)g->base,
(unsigned long long)g->size,
(unsigned long long)h->base,
(unsigned long long)h->size);
if (apertures_overlap(g, h))
return true;
}
}
return false;
}
#define VGA_FB_PHYS 0xA0000
void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{
int i;
/* check all firmware fbs and kick off if the base addr overlaps */
for (i = 0 ; i < FB_MAX; i++) {
struct apertures_struct *gen_aper;
if (!registered_fb[i])
continue;
if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
continue;
gen_aper = registered_fb[i]->apertures;
if (fb_do_apertures_overlap(gen_aper, a) ||
(primary && gen_aper && gen_aper->count &&
gen_aper->ranges[0].base == VGA_FB_PHYS)) {
printk(KERN_ERR "fb: conflicting fb hw usage "
"%s vs %s - removing generic driver\n",
name, registered_fb[i]->fix.id);
unregister_framebuffer(registered_fb[i]);
}
}
}
EXPORT_SYMBOL(remove_conflicting_framebuffers);
/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure

75
drivers/video/msm/Kconfig Normal file → Executable file
View File

@ -1,3 +1,26 @@
config FB_MSM
tristate "MSM Framebuffer"
depends on FB && ARCH_MSM
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
default y
config FB_MSM_MDP_PPP
bool "MSM MDP PPP"
depends on FB_MSM_LEGACY_MDP
default y
config FB_MSM_LCDC
bool "Support for integrated LCD controller in MDP3/4"
depends on FB_MSM && (MSM_MDP31 || MSM_MDP302 || MSM_MDP40)
default y
config FB_MSM_MDDI
bool "Support for MSM MDDI controllers"
depends on FB_MSM
default y
config FB_MSM
tristate
depends on FB && ARCH_MSM
@ -6,43 +29,35 @@ config FB_MSM
select FB_CFB_IMAGEBLIT
default y
config FB_MSM_LEGACY_MDP
bool "MSM Legacy MDP (qsd8k)"
depends on FB_MSM && (MSM_MDP30 || MSM_MDP31 || MSM_MDP302)
default y
config FB_MSM_MDP_PPP
bool "MSM MDP PPP"
depends on FB_MSM_LEGACY_MDP
default y
config FB_MSM_LCDC
bool "Support for integrated LCD controller in qsd8x50 and MSM7x27"
depends on FB_MSM && (MSM_MDP31 || MSM_MDP302)
bool "Support for integrated LCD controller in qsd8x50 ,MSM7x27 and MSM7x30"
depends on FB_MSM && (MSM_MDP31 || MSM_MDP302 || MSM_MDP40)
default y
config FB_MSM_TVOUT
bool "Support for TV-Out in qsd8x50"
depends on FB_MSM && MSM_MDP31
default n
config FB_MSM_OVERLAY
bool "Support for overlay in MSM7X30"
depends on FB_MSM && MSM_MDP40
config FB_MSM_MDDI
bool "Support for MSM MDDI controllers"
depends on FB_MSM
default y
config FB_MSM_DTV
depends on FB_MSM_OVERLAY
bool
config FB_MSM_MDDI_EPSON
bool "Support for Epson MDDI panels"
depends on FB_MSM_MDDI
default n
config MSM_ROTATOR
tristate "MSM Offline Image Rotator Driver"
depends on ARCH_MSM7X30 && ANDROID_PMEM
default y
help
This driver provides support for the image rotator HW block in the
MSM 7x30 SoC.
config MSM_ROTATOR_USE_IMEM
bool "Enable rotator driver to use iMem"
depends on MSM_ROTATOR
default y
help
This option enables the msm_rotator driver to use the move efficient
iMem. Some MSM platforms may not have iMem available for the rotator
block. Or some systems may want the iMem to be dedicated to a
different function.
config FB_MSM_MDDI_NOVTEC
bool "Support for Novtec MDDI panels"
depends on FB_MSM_MDDI
default n
config MSM_HDMI
bool "Support for HDMI in QCT platform"

7
drivers/video/msm/Makefile Normal file → Executable file
View File

@ -14,6 +14,8 @@ obj-$(CONFIG_FB_MSM_OVERLAY) += mdp4_overlay.o
obj-$(CONFIG_FB_MSM_OVERLAY) += mdp4_overlay_mddi.o
obj-$(CONFIG_MSM_MDP40) += msm_rotator.o
obj-$(CONFIG_FB_MSM_LEGACY_MDP) += mdp_hw_legacy.o
obj-$(CONFIG_MSM_MDP22) += mdp_ppp22.o
obj-$(CONFIG_MSM_MDP30) += mdp_ppp22.o
obj-$(CONFIG_MSM_MDP302)+= mdp_ppp22.o
@ -25,11 +27,10 @@ obj-y += mddi.o
# MDDI client/panel drivers
#
obj-y += mddi_client_dummy.o
obj-y += mddi_client_simple.o
obj-y += mddi_client_toshiba.o
obj-y += mddi_client_epson.o
obj-y += mddi_client_novb9f6_5582.o
# MDP LCD controller driver
obj-$(CONFIG_FB_MSM_LCDC) += mdp_lcdc.o
obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o tvfb.o

View File

@ -31,7 +31,7 @@
#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/wakelock.h>
#include <asm/uaccess.h>
#include <mach/msm_fb.h>
#include "mddi_hw.h"
@ -106,7 +106,9 @@ struct mddi_info {
};
static void mddi_init_rev_encap(struct mddi_info *mddi);
/* FIXME: Workaround for Novatek
static void mddi_skew_calibration(struct mddi_info *mddi);
*/
#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
@ -204,10 +206,8 @@ static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
{
union mddi_rev *rev = mddi->rev_data;
uint32_t rev_data_count;
uint32_t rev_crc_err_count;
int i;
struct reg_read_info *ri;
size_t prev_offset;
uint16_t length;
@ -242,6 +242,8 @@ static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
return;
if (mddi_debug_flags & 1) {
int i;
union mddi_rev *rev = mddi->rev_data;
printk(KERN_INFO "INT %x, STAT %x, CURR_REV_PTR %x\n",
mddi_readl(INT), mddi_readl(STAT),
mddi_readl(CURR_REV_PTR));
@ -355,7 +357,7 @@ static irqreturn_t mddi_isr(int irq, void *data)
static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
uint32_t intmask, int timeout)
{
unsigned long irq_flags;
unsigned long irq_flags=0;
spin_lock_irqsave(&mddi->int_lock, irq_flags);
mddi->got_int &= ~intmask;
@ -369,7 +371,7 @@ static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
{
if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
printk(KERN_INFO KERN_ERR "mddi_wait_interrupt %d, timeout "
printk(KERN_INFO "mddi_wait_interrupt %d, timeout "
"waiting for %x, INT = %x, STAT = %x gotint = %x\n",
current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
mddi->got_int);
@ -399,7 +401,10 @@ static uint16_t mddi_init_registers(struct mddi_info *mddi)
mddi_writel(0x0001, VERSION);
mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
mddi_writel(0x0003, SPM); /* subframes per media */
mddi_writel(0x0005, TA1_LEN);
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
mddi_writel(0x00C8, TA1_LEN);
else
mddi_writel(0x0005, TA1_LEN);
mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
@ -431,7 +436,7 @@ static uint16_t mddi_init_registers(struct mddi_info *mddi)
mddi_writel(0x0050, DRIVE_LO);
mddi_writel(0x00320000, PAD_IO_CTL);
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
mddi_writel(0x40884020, PAD_CAL);
mddi_writel(0x40880020, PAD_CAL);
else
mddi_writel(0x00220020, PAD_CAL);
#else
@ -469,7 +474,7 @@ static void mddi_suspend(struct msm_mddi_client_data *cdata)
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
/* turn off the clock */
clk_disable(mddi->clk);
#if CONFIG_MSM_MDP40
#ifdef CONFIG_MSM_MDP40
clk_disable(mdp_clk);
#endif
wake_unlock(&mddi->idle_lock);
@ -484,7 +489,7 @@ static void mddi_resume(struct msm_mddi_client_data *cdata)
/* turn on the client */
if (mddi->power_client)
mddi->power_client(&mddi->client_data, 1);
#if CONFIG_MSM_MDP40
#ifdef CONFIG_MSM_MDP40
clk_enable(mdp_clk);
#endif
/* turn on the clock */
@ -498,7 +503,8 @@ static void mddi_resume(struct msm_mddi_client_data *cdata)
*/
mddi_writel(mddi->int_enable, INTEN);
mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
mddi_writel(MDDI_CMD_SEND_RTD, CMD);
if (mddi->type == MSM_MDP_MDDI_TYPE_I)
mddi_writel(MDDI_CMD_SEND_RTD, CMD);
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
mddi_set_auto_hibernate(&mddi->client_data, 1);
wake_unlock(&mddi->idle_lock);
@ -689,7 +695,7 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
struct reg_read_info ri;
unsigned s;
int retry_count = 2;
unsigned long irq_flags;
unsigned long irq_flags=0;
mutex_lock(&mddi->reg_read_lock);
@ -720,6 +726,9 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
do {
init_completion(&ri.done);
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
mddi_set_auto_hibernate(&mddi->client_data, 0);
mddi_writel(MDDI_CMD_SEND_RTD, CMD);
mddi->reg_read = &ri;
mddi_writel(mddi->reg_read_addr, PRI_PTR);
@ -732,10 +741,14 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
/* while((s & MDDI_STAT_PRI_LINK_LIST_DONE) == 0){ */
/* s = mddi_readl(STAT); */
/* } */
/* Enable Periodic Reverse Encapsulation. */
mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
if (mddi->type == MSM_MDP_MDDI_TYPE_II) {
mddi_writel(MDDI_CMD_SEND_REV_ENCAP, CMD);
mddi_wait_interrupt(mddi, MDDI_INT_REV_DATA_AVAIL);
} else {
/* Enable Periodic Reverse Encapsulation. */
mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
}
if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
!ri.done.done) {
printk(KERN_INFO "mddi_remote_read(%x) timeout "
@ -763,6 +776,8 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
"MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
"curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
if (mddi->type == MSM_MDP_MDDI_TYPE_II)
mddi_set_auto_hibernate(&mddi->client_data, 1);
} while (retry_count-- > 0);
/* Disable Periodic Reverse Encapsulation. */
mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
@ -830,7 +845,7 @@ static int __init mddi_rev_data_setup(struct mddi_info *mddi)
sizeof(*mddi->reg_write_data);
return 0;
}
/* FIXME: Workaround for Novatek
static void mddi_skew_calibration(struct mddi_info *mddi)
{
struct msm_mddi_platform_data *pdata = mddi->client_pdev.dev.platform_data;
@ -842,6 +857,7 @@ static void mddi_skew_calibration(struct mddi_info *mddi)
clk_set_rate( mddi->clk, pdata->clk_rate);
mdelay(1);
}
*/
static int __init mddi_probe(struct platform_device *pdev)
{
@ -871,7 +887,7 @@ static int __init mddi_probe(struct platform_device *pdev)
printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
mddi->irq);
mddi->power_client = pdata->power_client;
if (pdata->type != NULL)
if ((pdata->type != NULL) && (pdata->type != MSM_MDP_MDDI_TYPE_I))
mddi->type = pdata->type;
mutex_init(&mddi->reg_write_lock);

View File

@ -1,97 +0,0 @@
/* drivers/video/msm_fb/mddi_client_dummy.c
*
* Support for "dummy" mddi client devices which require no
* special initialization code.
*
* Copyright (C) 2007 Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <mach/msm_fb.h>
struct panel_info {
struct platform_device pdev;
struct msm_panel_data panel_data;
};
static int mddi_dummy_suspend(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_resume(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_blank(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_unblank(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_probe(struct platform_device *pdev)
{
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
struct panel_info *panel =
kzalloc(sizeof(struct panel_info), GFP_KERNEL);
int ret;
if (!panel)
return -ENOMEM;
platform_set_drvdata(pdev, panel);
panel->panel_data.suspend = mddi_dummy_suspend;
panel->panel_data.resume = mddi_dummy_resume;
panel->panel_data.blank = mddi_dummy_blank;
panel->panel_data.unblank = mddi_dummy_unblank;
panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
panel->pdev.name = "msm_panel";
panel->pdev.id = pdev->id;
platform_device_add_resources(&panel->pdev,
client_data->fb_resource, 1);
panel->panel_data.fb_data = client_data->private_client_data;
panel->pdev.dev.platform_data = &panel->panel_data;
ret = platform_device_register(&panel->pdev);
if (ret) {
kfree(panel);
return ret;
}
return 0;
}
static int mddi_dummy_remove(struct platform_device *pdev)
{
struct panel_info *panel = platform_get_drvdata(pdev);
kfree(panel);
return 0;
}
static struct platform_driver mddi_client_dummy = {
.probe = mddi_dummy_probe,
.remove = mddi_dummy_remove,
.driver = { .name = "mddi_c_dummy" },
};
static int __init mddi_client_dummy_init(void)
{
platform_driver_register(&mddi_client_dummy);
return 0;
}
module_init(mddi_client_dummy_init);

View File

@ -19,6 +19,8 @@
#include <linux/gpio.h>
#include <linux/wakelock.h>
#include <mach/msm_fb.h>
#include <linux/slab.h>
#include <linux/sched.h>
static DECLARE_WAIT_QUEUE_HEAD(epson_vsync_wait);

View File

@ -19,6 +19,8 @@
#include <linux/gpio.h>
#include <linux/wakelock.h>
#include <mach/msm_fb.h>
#include <linux/slab.h>
#include <linux/sched.h>
static DECLARE_WAIT_QUEUE_HEAD(novtec_vsync_wait);
@ -145,7 +147,6 @@ static irqreturn_t novtec_vsync_interrupt(int irq, void *data)
panel->novtec_got_int = 1;
if (panel->novtec_callback) {
mdelay(3);
panel->novtec_callback->func(panel->novtec_callback);
panel->novtec_callback = 0;
}

View File

@ -21,6 +21,7 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <mach/msm_fb.h>
static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);

View File

@ -0,0 +1,236 @@
/* drivers/video/msm_fb/mddi_client_simple.c
*
* Support for simple mddi client devices which require no special
* initialization code except for what may be provided in the board file.
* If the clients do not provide board specific code, this driver's
* panel operations are no-ops.
*
* Copyright (C) 2007-2010, Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*/
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <mach/msm_fb.h>
struct panel_info {
struct platform_device pdev;
struct msm_mddi_client_data *client_data;
struct msm_panel_data panel_data;
struct msmfb_callback *fb_callback;
wait_queue_head_t vsync_wait;
int got_vsync;
int irq;
};
#define to_panel_info(pd) container_of((pd), struct panel_info, panel_data)
static void mddi_simple_request_vsync(struct msm_panel_data *panel_data,
struct msmfb_callback *callback)
{
struct panel_info *panel = to_panel_info(panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
panel->fb_callback = callback;
if (panel->got_vsync) {
panel->got_vsync = 0;
client_data->activate_link(client_data); /* clears interrupt */
}
}
static void mddi_simple_wait_vsync(struct msm_panel_data *panel_data)
{
struct panel_info *panel = to_panel_info(panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
int ret;
if (panel->got_vsync) {
panel->got_vsync = 0;
client_data->activate_link(client_data); /* clears interrupt */
}
ret = wait_event_timeout(panel->vsync_wait, panel->got_vsync, HZ/2);
if (!ret && !panel->got_vsync)
pr_err("mddi_client_simple: timeout waiting for vsync\n");
panel->got_vsync = 0;
/* interrupt clears when screen dma starts */
}
static int mddi_simple_suspend(struct msm_panel_data *panel_data)
{
struct panel_info *panel = to_panel_info(panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
int ret;
if (!bridge_data->uninit)
return 0;
ret = bridge_data->uninit(bridge_data, client_data);
if (ret) {
pr_info("%s: non zero return from uninit\n", __func__);
return ret;
}
client_data->suspend(client_data);
return 0;
}
static int mddi_simple_resume(struct msm_panel_data *panel_data)
{
struct panel_info *panel = to_panel_info(panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
if (!bridge_data->init)
return 0;
client_data->resume(client_data);
return bridge_data->init(bridge_data, client_data);
}
static int mddi_simple_blank(struct msm_panel_data *panel_data)
{
struct panel_info *panel = to_panel_info(panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
if (!bridge_data->blank)
return 0;
return bridge_data->blank(bridge_data, client_data);
}
static int mddi_simple_unblank(struct msm_panel_data *panel_data)
{
struct panel_info *panel = to_panel_info(panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
if (!bridge_data->unblank)
return 0;
return bridge_data->unblank(bridge_data, client_data);
}
static irqreturn_t handle_vsync_irq(int irq, void *data)
{
struct panel_info *panel = data;
panel->got_vsync = 1;
if (panel->fb_callback) {
panel->fb_callback->func(panel->fb_callback);
panel->fb_callback = NULL;
}
wake_up(&panel->vsync_wait);
return IRQ_HANDLED;
}
static int mddi_simple_probe(struct platform_device *pdev)
{
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
struct panel_info *panel;
int ret;
pr_debug("%s()\n", __func__);
panel = kzalloc(sizeof(struct panel_info), GFP_KERNEL);
if (!panel)
return -ENOMEM;
platform_set_drvdata(pdev, panel);
init_waitqueue_head(&panel->vsync_wait);
panel->irq = platform_get_irq_byname(pdev, "vsync");
if (panel->irq >= 0) {
ret = request_irq(panel->irq, handle_vsync_irq,
IRQF_TRIGGER_RISING, "mddi_c_simple_vsync",
panel);
if (ret) {
pr_err("%s: request vsync irq %d failed (%d)\n",
__func__, panel->irq, ret);
goto err_req_irq;
}
panel->panel_data.wait_vsync = mddi_simple_wait_vsync;
panel->panel_data.request_vsync = mddi_simple_request_vsync;
}
panel->client_data = client_data;
panel->panel_data.suspend = mddi_simple_suspend;
panel->panel_data.resume = mddi_simple_resume;
panel->panel_data.blank = mddi_simple_blank;
panel->panel_data.unblank = mddi_simple_unblank;
panel->panel_data.caps = bridge_data->caps;
panel->panel_data.fb_data = &bridge_data->fb_data;
panel->pdev.name = "msm_panel";
panel->pdev.id = pdev->id;
platform_device_add_resources(&panel->pdev,
client_data->fb_resource, 1);
panel->pdev.dev.platform_data = &panel->panel_data;
if (bridge_data->init)
bridge_data->init(bridge_data, client_data);
ret = platform_device_register(&panel->pdev);
if (ret) {
pr_err("%s: Can't register platform device\n", __func__);
goto err_plat_dev_reg;
}
return 0;
err_plat_dev_reg:
if (panel->irq >= 0)
free_irq(panel->irq, panel);
err_req_irq:
platform_set_drvdata(pdev, NULL);
kfree(panel);
return ret;
}
static int mddi_simple_remove(struct platform_device *pdev)
{
struct panel_info *panel = platform_get_drvdata(pdev);
kfree(panel);
return 0;
}
static struct platform_driver mddi_client_simple = {
.probe = mddi_simple_probe,
.remove = mddi_simple_remove,
.driver = {
.owner = THIS_MODULE,
.name = "mddi_c_simple"
},
};
static int __init mddi_client_simple_init(void)
{
platform_driver_register(&mddi_client_simple);
return 0;
}
module_init(mddi_client_simple_init);

View File

@ -21,6 +21,7 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <mach/msm_fb.h>

View File

@ -53,8 +53,9 @@
#define MDDI_MF_CNT 0x0084
#define MDDI_CURR_REV_PTR 0x0088
#define MDDI_CORE_VER 0x008c
#define MDDI_PAD_IO_CTL 0x00a0
#define MDDI_PAD_CAL 0x00a4
#define MDDI_SF_LEN_CTL_REG 0x0094
#define MDDI_PAD_IO_CTL 0x00a0
#define MDDI_PAD_CAL 0x00a4
#define MDDI_INT_PRI_PTR_READ 0x0001
#define MDDI_INT_SEC_PTR_READ 0x0002
@ -131,8 +132,10 @@
#define MDDI_HOST_TA2_LEN 0x000c
#endif
#if defined (CONFIG_ARCH_QSD8X50) || defined (CONFIG_ARCH_MSM7X30)
#if defined (CONFIG_ARCH_QSD8X50)
#define MDDI_HOST_REV_RATE_DIV 0x0004
#elif defined (CONFIG_ARCH_MSM7X30)
#define MDDI_HOST_REV_RATE_DIV 0x0010
#else
#define MDDI_HOST_REV_RATE_DIV 0x0002
#endif

View File

@ -21,10 +21,10 @@
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/clk.h>
#include <linux/timer.h>
#include <linux/file.h>
#include <linux/android_pmem.h>
#include <linux/major.h>
#include <linux/msm_hw3d.h>
#include <mach/msm_iomap.h>
#include <mach/msm_fb.h>
@ -36,10 +36,16 @@
struct class *mdp_class;
#ifdef CONFIG_MSM_HDMI
/* Used to report LCDC underflows */
void reportUnderflow(void);
#endif
#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
static unsigned int mdp_irq_mask;
static unsigned int mdp_dma_timer_enable = 0;
struct clk *mdp_clk_to_disable_later = 0;
static struct mdp_blit_req *timeout_req;
#ifdef CONFIG_FB_MSM_OVERLAY
@ -53,7 +59,19 @@ extern void mdp4_mddi_overlay(void *priv, uint32_t addr, uint32_t stride,
uint32_t y);
#include "mdp4.h"
#endif
DEFINE_MUTEX(mdp_mutex);
static void mdp_do_standby_timer(unsigned long data)
{
struct mdp_info *mdp = (struct mdp_info *) data;
if (!mdp_irq_mask) {
clk_set_rate(mdp->ebi1_clk, 0);
mdp->state |= MDP_STATE_STANDBY;
} else {
mod_timer(&mdp->standby_timer,
jiffies + msecs_to_jiffies(200));
}
}
static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
{
@ -69,7 +87,17 @@ static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
if (!mdp_irq_mask) {
clk_enable(mdp->clk);
enable_irq(mdp->irq);
clk_set_rate(mdp->ebi1_clk, 128000000);
if (mdp->state & MDP_STATE_STANDBY) {
#ifdef CONFIG_MSM_MDP40
clk_set_rate(mdp->ebi1_clk, 153000000);
#else
clk_set_rate(mdp->ebi1_clk, 128000000);
#endif
mdp->state &= ~MDP_STATE_STANDBY;
} else {
del_timer_sync(&mdp->standby_timer);
barrier();
}
}
/* clear out any previous irqs for the requested mask*/
@ -84,7 +112,7 @@ static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
{
unsigned long flags;
unsigned long flags=0;
int ret;
spin_lock_irqsave(&mdp->lock, flags);
@ -111,14 +139,16 @@ static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
disable_irq_nosync(mdp->irq);
if (mdp->clk)
clk_disable(mdp->clk);
clk_set_rate(mdp->ebi1_clk, 0);
if (!(mdp->state & MDP_STATE_STANDBY))
mod_timer(&mdp->standby_timer,
jiffies + msecs_to_jiffies(200));
}
return 0;
}
int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
{
unsigned long irq_flags;
unsigned long irq_flags=0;
int ret;
spin_lock_irqsave(&mdp->lock, irq_flags);
@ -130,7 +160,7 @@ int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
static irqreturn_t mdp_isr(int irq, void *data)
{
uint32_t status;
unsigned long irq_flags;
unsigned long irq_flags=0;
struct mdp_info *mdp = data;
int i;
@ -139,13 +169,22 @@ static irqreturn_t mdp_isr(int irq, void *data)
status = mdp_readl(mdp, MDP_INTR_STATUS);
mdp_writel(mdp, status, MDP_INTR_CLEAR);
#if defined(CONFIG_MACH_HTCLEO)
status &= ~0x10000; // Cotulla
#endif
// pr_info("%s: status=%08x (irq_mask=%08x)\n", __func__, status,
// mdp_irq_mask);
if (mdp_dma_timer_enable) {
del_timer_sync(&mdp->dma_timer);
mdp_dma_timer_enable = 0;
}
#ifdef CONFIG_MSM_HDMI
if (status & MDP_LCDC_UNDERFLOW)
{
pr_err("%s: LCDC Underflow\n", __func__);
reportUnderflow();
}
#endif
status &= ~0x10000; // Cotulla
status &= mdp_irq_mask;
#ifdef CONFIG_MSM_MDP40
if (mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
@ -168,9 +207,9 @@ static irqreturn_t mdp_isr(int irq, void *data)
}
}
if (status & DL0_ROI_DONE)
wake_up(&mdp_ppp_waitqueue);
#ifndef CONFIG_MSM_MDP40
mdp_ppp_handle_isr(mdp, status);
#endif
if (status)
locked_disable_mdp_irq(mdp, status);
@ -178,10 +217,43 @@ static irqreturn_t mdp_isr(int irq, void *data)
return IRQ_HANDLED;
}
static void mdp_do_dma_timer(unsigned long data)
{
uint32_t status;
struct mdp_info *mdp = (struct mdp_info *) data;
unsigned long irq_flags=0;
int i;
spin_lock_irqsave(&mdp->lock, irq_flags);
status = mdp_readl(mdp, MDP_INTR_STATUS);
mdp_writel(mdp, mdp_irq_mask, MDP_INTR_CLEAR);
for (i = 0; i < MSM_MDP_NUM_INTERFACES; ++i) {
struct mdp_out_interface *out_if = &mdp->out_if[i];
if (mdp_irq_mask & out_if->dma_mask) {
if (out_if->dma_cb) {
out_if->dma_cb->func(out_if->dma_cb);
out_if->dma_cb = NULL;
}
wake_up(&out_if->dma_waitqueue);
}
if (mdp_irq_mask & out_if->irq_mask) {
out_if->irq_cb->func(out_if->irq_cb);
out_if->irq_cb = NULL;
}
}
locked_disable_mdp_irq(mdp, mdp_irq_mask);
spin_unlock_irqrestore(&mdp->lock, irq_flags);
}
static uint32_t mdp_check_mask(struct mdp_info *mdp, uint32_t mask)
{
uint32_t ret;
unsigned long irq_flags;
unsigned long irq_flags=0;
spin_lock_irqsave(&mdp->lock, irq_flags);
ret = mdp_irq_mask & mask;
@ -189,10 +261,29 @@ static uint32_t mdp_check_mask(struct mdp_info *mdp, uint32_t mask)
return ret;
}
static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
void mdp_dump_blit(struct mdp_blit_req *req)
{
pr_info("%s: src: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
req->src.width, req->src.height, req->src.format,
req->src.offset, req->src.memory_id);
pr_info("%s: dst: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
req->dst.width, req->dst.height, req->dst.format,
req->dst.offset, req->dst.memory_id);
pr_info("%s: src_rect: x=%d y=%d w=%d h=%d\n", __func__,
req->src_rect.x, req->src_rect.y, req->src_rect.w,
req->src_rect.h);
pr_info("%s: dst_rect: x=%d y=%d w=%d h=%d\n", __func__,
req->dst_rect.x, req->dst_rect.y, req->dst_rect.w,
req->dst_rect.h);
pr_info("%s: alpha=0x%08x\n", __func__, req->alpha);
pr_info("%s: transp_max=0x%08x\n", __func__, req->transp_mask);
pr_info("%s: flags=%08x\n", __func__, req->flags);
}
int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
{
int ret = 0;
unsigned long irq_flags;
unsigned long irq_flags=0;
// pr_info("%s: WAITING for 0x%x\n", __func__, mask);
wait_event_timeout(*wq, !mdp_check_mask(mdp, mask), HZ);
@ -214,7 +305,7 @@ static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
return ret;
}
void mdp_dma_wait(struct mdp_device *mdp_dev, int interface)
static void mdp_dma_wait(struct mdp_device *mdp_dev, int interface)
{
#define MDP_MAX_TIMEOUTS 20
static int timeout_count;
@ -247,54 +338,42 @@ void mdp_dma_wait(struct mdp_device *mdp_dev, int interface)
BUG();
}
}
/*
static int mdp_ppp_wait(struct mdp_info *mdp)
{
return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
}
*/
#ifndef CONFIG_MSM_MDP40
static void mdp_dmas_to_mddi(void *priv, uint32_t addr, uint32_t stride,
uint32_t width, uint32_t height, uint32_t x, uint32_t y)
{
struct mdp_info *mdp = priv;
uint32_t dma2_cfg;
uint32_t video_packet_parameter;
uint32_t video_packet_parameter = 0;
uint16_t ld_param = 1;
dma2_cfg = DMA_PACK_TIGHT |
DMA_PACK_ALIGN_LSB |
DMA_OUT_SEL_AHB |
DMA_IBUF_NONCONTIGUOUS;
if(machine_is_htcleo()) {
dma2_cfg = DMA_PACK_ALIGN_MSB |
DMA_PACK_PATTERN_RGB;
dma2_cfg |= mdp->dma_format;
dma2_cfg |= mdp->format;
#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
if (mdp->dma_format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
#else
if (mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888)
#endif
dma2_cfg |= DMA_PACK_PATTERN_BGR;
else
dma2_cfg |= DMA_PACK_PATTERN_RGB;
dma2_cfg |= DMA_OUT_SEL_LCDC;
dma2_cfg |= DMA_OUT_SEL_MDDI;
dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
} else {
dma2_cfg = DMA_PACK_TIGHT |
DMA_PACK_ALIGN_LSB |
DMA_OUT_SEL_AHB |
DMA_IBUF_NONCONTIGUOUS;
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
dma2_cfg |= mdp->format;
#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
if (mdp->format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
#else
if (mdp->format == DMA_IBUF_FORMAT_XRGB8888)
#endif
dma2_cfg |= DMA_PACK_PATTERN_BGR;
else
dma2_cfg |= DMA_PACK_PATTERN_RGB;
dma2_cfg |= DMA_OUT_SEL_MDDI;
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
dma2_cfg |= DMA_DITHER_EN;
}
dma2_cfg |= DMA_DITHER_EN;
if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565) {
dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
@ -341,12 +420,12 @@ static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
DMA_IBUF_NONCONTIGUOUS;
#endif
dma2_cfg |= mdp->format;
dma2_cfg |= mdp->dma_format;
#if defined CONFIG_MSM_MDP22 || defined CONFIG_MSM_MDP30
if (mdp->format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
if (mdp->dma_format == DMA_IBUF_FORMAT_RGB888_OR_ARGB8888)
#else
if (mdp->format == DMA_IBUF_FORMAT_XRGB8888)
if (mdp->dma_format == DMA_IBUF_FORMAT_XRGB8888)
#endif
dma2_cfg |= DMA_PACK_PATTERN_BGR;
else
@ -417,6 +496,7 @@ static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
mdp_writel(mdp, 0, MDP_DMA_P_START);
#endif
}
#endif /* ifndef CONFIG_MSM_MDP40 */
void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
uint32_t width, uint32_t height, uint32_t x, uint32_t y,
@ -435,54 +515,21 @@ void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
spin_lock_irqsave(&mdp->lock, flags);
if (locked_enable_mdp_irq(mdp, out_if->dma_mask)) {
/* something wrong in dma, workaround it */
mdp_dma_timer_enable = 1;
pr_err("%s: busy\n", __func__);
goto done;
}
out_if->dma_cb = callback;
out_if->dma_start(out_if->priv, addr, stride, width, height, x, y);
done:
if (mdp_dma_timer_enable)
mod_timer(&mdp->dma_timer,
jiffies + msecs_to_jiffies(17));
spin_unlock_irqrestore(&mdp->lock, flags);
}
static int get_img(struct mdp_img *img, struct fb_info *info,
unsigned long *start, unsigned long *len,
struct file** filep)
{
int put_needed, ret = 0;
struct file *file;
unsigned long vstart;
if (!get_pmem_file(img->memory_id, start, &vstart, len, filep))
return 0;
else if (!get_msm_hw3d_file(img->memory_id, &img->offset, start, len,
filep))
return 0;
file = fget_light(img->memory_id, &put_needed);
if (file == NULL)
return -1;
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
*start = info->fix.smem_start;
*len = info->fix.smem_len;
ret = 0;
} else
ret = -1;
fput_light(file, put_needed);
return ret;
}
static void put_img(struct file *file)
{
if (file) {
if (is_pmem_file(file))
put_pmem_file(file);
else if (is_msm_hw3d_file(file))
put_msm_hw3d_file(file);
}
}
void mdp_configure_dma(struct mdp_device *mdp_dev)
{
@ -494,7 +541,7 @@ void mdp_configure_dma(struct mdp_device *mdp_dev)
dma_cfg = mdp_readl(mdp, MDP_DMA_P_CONFIG);
dma_cfg &= ~DMA_IBUF_FORMAT_MASK;
dma_cfg &= ~DMA_PACK_PATTERN_MASK;
dma_cfg |= (mdp->format | mdp->pack_pattern);
dma_cfg |= (mdp->dma_format | mdp->dma_pack_pattern);
mdp_writel(mdp, dma_cfg, MDP_DMA_P_CONFIG);
mdp->dma_config_dirty = false;
@ -514,6 +561,13 @@ int mdp_check_output_format(struct mdp_device *mdp_dev, int bpp)
return 0;
}
void mdp_set_panel_size(struct mdp_device *mdp_dev, int width, int height)
{
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
mdp->mdp_dev.width = width;
mdp->mdp_dev.height = height;
}
int mdp_set_output_format(struct mdp_device *mdp_dev, int bpp)
{
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
@ -542,214 +596,24 @@ int mdp_set_output_format(struct mdp_device *mdp_dev, int bpp)
default:
return -EINVAL;
}
if (format != mdp->format || pack_pattern != mdp->pack_pattern) {
mdp->format = format;
mdp->pack_pattern = pack_pattern;
if (format != mdp->dma_format || pack_pattern != mdp->dma_pack_pattern) {
mdp->dma_format = format;
mdp->dma_pack_pattern = pack_pattern;
mdp->dma_config_dirty = true;
}
return 0;
}
static void dump_req(struct mdp_blit_req *req,
unsigned long src_start, unsigned long src_len,
unsigned long dst_start, unsigned long dst_len)
{
pr_err("flags: 0x%x\n", req->flags);
pr_err("src_start: 0x%08lx\n", src_start);
pr_err("src_len: 0x%08lx\n", src_len);
pr_err("src.offset: 0x%x\n", req->src.offset);
pr_err("src.format: 0x%x\n", req->src.format);
pr_err("src.width: %d\n", req->src.width);
pr_err("src.height: %d\n", req->src.height);
pr_err("src_rect.x: %d\n", req->src_rect.x);
pr_err("src_rect.y: %d\n", req->src_rect.y);
pr_err("src_rect.w: %d\n", req->src_rect.w);
pr_err("src_rect.h: %d\n", req->src_rect.h);
pr_err("dst_start: 0x%08lx\n", dst_start);
pr_err("dst_len: 0x%08lx\n", dst_len);
pr_err("dst.offset: 0x%x\n", req->dst.offset);
pr_err("dst.format: 0x%x\n", req->dst.format);
pr_err("dst.width: %d\n", req->dst.width);
pr_err("dst.height: %d\n", req->dst.height);
pr_err("dst_rect.x: %d\n", req->dst_rect.x);
pr_err("dst_rect.y: %d\n", req->dst_rect.y);
pr_err("dst_rect.w: %d\n", req->dst_rect.w);
pr_err("dst_rect.h: %d\n", req->dst_rect.h);
}
int mdp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
{
int ret;
enable_mdp_irq(mdp, DL0_ROI_DONE);
ret = mdp_ppp_blit(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
if (unlikely(ret)) {
disable_mdp_irq(mdp, DL0_ROI_DONE);
return ret;
}
ret = mdp_ppp_wait(mdp);
if (unlikely(ret)) {
printk(KERN_ERR "%s: failed!\n", __func__);
pr_err("original request:\n");
dump_req(mdp->req, src_start, src_len, dst_start, dst_len);
pr_err("dead request:\n");
dump_req(req, src_start, src_len, dst_start, dst_len);
BUG();
return ret;
}
return 0;
}
int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
struct mdp_blit_req *req)
{
int ret;
unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
struct file *src_file = 0, *dst_file = 0;
#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP302)
if (req->flags & MDP_ROT_90) {
if (unlikely(((req->dst_rect.h == 1) &&
((req->src_rect.w != 1) ||
(req->dst_rect.w != req->src_rect.h))) ||
((req->dst_rect.w == 1) && ((req->src_rect.h != 1) ||
(req->dst_rect.h != req->src_rect.w))))) {
pr_err("mpd_ppp: error scaling when size is 1!\n");
return -EINVAL;
}
} else {
if (unlikely(((req->dst_rect.w == 1) &&
((req->src_rect.w != 1) ||
(req->dst_rect.h != req->src_rect.h))) ||
((req->dst_rect.h == 1) && ((req->src_rect.h != 1) ||
(req->dst_rect.h != req->src_rect.h))))) {
pr_err("mpd_ppp: error scaling when size is 1!\n");
return -EINVAL;
}
}
#endif
/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
if (unlikely(req->src_rect.h == 0 ||
req->src_rect.w == 0)) {
printk(KERN_ERR "mdp_ppp: src img of zero size!\n");
return -EINVAL;
}
if (unlikely(req->dst_rect.h == 0 ||
req->dst_rect.w == 0))
return -EINVAL;
/* do this first so that if this fails, the caller can always
* safely call put_img */
if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
printk(KERN_ERR "mdp_ppp: could not retrieve src image from "
"memory\n");
return -EINVAL;
}
if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
printk(KERN_ERR "mdp_ppp: could not retrieve dst image from "
"memory\n");
put_img(src_file);
return -EINVAL;
}
mutex_lock(&mdp_mutex);
timeout_req = req;
/* transp_masking unimplemented */
req->transp_mask = MDP_TRANSP_NOP;
mdp->req = req;
#if !defined(CONFIG_MSM_MDP31) && !defined(CONFIG_MSM_MDP302)
if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
req->alpha != MDP_ALPHA_NOP ||
HAS_ALPHA(req->src.format)) &&
(req->flags & MDP_ROT_90 &&
req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
int i;
unsigned int tiles = req->dst_rect.h / 16;
unsigned int remainder = req->dst_rect.h % 16;
req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
req->dst_rect.h = 16;
for (i = 0; i < tiles; i++) {
ret = mdp_blit_and_wait(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
if (ret)
goto end;
req->dst_rect.y += 16;
req->src_rect.x += req->src_rect.w;
}
if (!remainder)
goto end;
req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
req->dst_rect.h = remainder;
}
#else
/* Workarounds for MDP 3.1 hardware bugs */
if (unlikely((mdp_get_bytes_per_pixel(req->dst.format) == 4) &&
(req->dst_rect.w != 1) &&
(((req->dst_rect.w % 8) == 6) ||
((req->dst_rect.w % 32) == 3) ||
((req->dst_rect.w % 32) == 1)))) {
ret = mdp_ppp_blit_split_width(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
goto end;
} else if (unlikely((req->dst_rect.w != 1) && (req->dst_rect.h != 1) &&
((req->dst_rect.h % 32) == 3 ||
(req->dst_rect.h % 32) == 1))) {
ret = mdp_ppp_blit_split_height(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
goto end;
}
#endif
ret = mdp_blit_and_wait(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
end:
put_img(src_file);
put_img(dst_file);
mutex_unlock(&mdp_mutex);
return ret;
return mdp_ppp_blit(mdp, fb, req);
}
int mdp_fb_mirror(struct mdp_device *mdp_dev,
struct fb_info *src_fb, struct fb_info *dst_fb,
struct mdp_blit_req *req)
{
int ret;
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
if (!src_fb || !dst_fb)
return -EINVAL;
enable_mdp_irq(mdp, DL0_ROI_DONE);
ret = mdp_ppp_blit(mdp, req,
-1, src_fb->fix.smem_start, src_fb->fix.smem_len,
-1, dst_fb->fix.smem_start, dst_fb->fix.smem_len);
if (ret)
goto err_bad_blit;
ret = mdp_ppp_wait(mdp);
if (ret) {
pr_err("mdp_ppp_wait error\n");
goto err_wait_failed;
}
return 0;
err_bad_blit:
disable_mdp_irq(mdp, DL0_ROI_DONE);
err_wait_failed:
return ret;
}
void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
{
@ -765,7 +629,7 @@ int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
mdp_dma_start_func_t dma_start)
{
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
unsigned long flags;
unsigned long flags=0;
int ret = 0;
if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES) {
@ -798,7 +662,7 @@ int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
uint32_t mask, struct msmfb_callback *cb)
{
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
unsigned long flags;
unsigned long flags=0;
int ret = 0;
if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES) {
@ -841,94 +705,6 @@ int register_mdp_client(struct class_interface *cint)
return class_interface_register(cint);
}
#ifdef CONFIG_MSM_MDP40
void mdp_hw_init(struct mdp_info *mdp)
{
mdp_irq_mask = 0;
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
}
#else
#include "mdp_csc_table.h"
void mdp_check_tearing(struct mdp_info *mdp, struct msm_mdp_platform_data *pdata)
{
mdp_writel(mdp, pdata->sync_config, MDP_SYNC_CONFIG_0);
mdp_writel(mdp, 1, MDP_TEAR_CHECK_EN);
mdp_writel(mdp, pdata->sync_thresh, MDP_SYNC_THRESH_0);
mdp_writel(mdp, pdata->sync_start_pos, MDP_PRIM_START_POS);
}
void mdp_hw_init(struct mdp_info *mdp)
{
int n;
int lcdc_enabled;
mdp_irq_mask = 0;
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
/* debug interface write access */
mdp_writel(mdp, 1, 0x60);
mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
#ifndef CONFIG_MSM_MDP22
lcdc_enabled = mdp_readl(mdp, MDP_LCDC_EN);
/* disable lcdc */
mdp_writel(mdp, 0, MDP_LCDC_EN);
/* enable auto clock gating for all blocks by default */
mdp_writel(mdp, 0xffffffff, MDP_CGC_EN);
/* reset color/gamma correct parms */
mdp_writel(mdp, 0, MDP_DMA_P_COLOR_CORRECT_CONFIG);
#endif
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
mdp_writel(mdp, 1, 0x60);
for (n = 0; n < ARRAY_SIZE(csc_color_lut); n++)
mdp_writel(mdp, csc_color_lut[n].val, csc_color_lut[n].reg);
/* clear up unused fg/main registers */
/* comp.plane 2&3 ystride */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
/* unpacked pattern */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
/* comp.plane 2 & 3 */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
/* clear unused bg registers */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
for (n = 0; n < ARRAY_SIZE(csc_matrix_config_table); n++)
mdp_writel(mdp, csc_matrix_config_table[n].val,
csc_matrix_config_table[n].reg);
mdp_ppp_init_scale(mdp);
#ifndef CONFIG_MSM_MDP31
mdp_writel(mdp, 0x04000400, MDP_COMMAND_CONFIG);
#endif
#ifndef CONFIG_MSM_MDP22
if(lcdc_enabled)
mdp_writel(mdp, 1, MDP_LCDC_EN);
#endif
}
#endif //CONFIG_MSM_MDP40
int mdp_probe(struct platform_device *pdev)
{
struct resource *resource;
@ -974,9 +750,13 @@ int mdp_probe(struct platform_device *pdev)
#endif
mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
mdp->mdp_dev.set_output_format = mdp_set_output_format;
mdp->mdp_dev.set_panel_size = mdp_set_panel_size;
mdp->mdp_dev.check_output_format = mdp_check_output_format;
mdp->mdp_dev.configure_dma = mdp_configure_dma;
mdp->enable_irq = enable_mdp_irq;
mdp->disable_irq = disable_mdp_irq;
if (pdata == NULL || pdata->overrides == 0)
mdp->mdp_dev.overrides = 0;
else if(pdata->overrides)
@ -987,27 +767,27 @@ int mdp_probe(struct platform_device *pdev)
else if(pdata->color_format)
mdp->mdp_dev.color_format = pdata->color_format;
if (pdata == NULL || pdata->dma_channel == MDP_DMA_P) {
#ifdef CONFIG_MSM_MDP40
if (mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
ret = mdp_out_if_register(&mdp->mdp_dev,
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE
| MDP_DMA_S_DONE, mdp4_mddi_overlay);
} else {
ret = mdp_out_if_register(&mdp->mdp_dev,
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE,
mdp4_mddi_overlay);
}
if (mdp->mdp_dev.overrides & MSM_MDP4_MDDI_DMA_SWITCH) {
ret = mdp_out_if_register(&mdp->mdp_dev,
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE
| MDP_DMA_S_DONE, mdp4_mddi_overlay);
} else {
ret = mdp_out_if_register(&mdp->mdp_dev,
MSM_MDDI_PMDH_INTERFACE, mdp, INTR_OVERLAY0_DONE,
mdp4_mddi_overlay);
}
#else
if (pdata == NULL || pdata->dma_channel == MDP_DMA_P) {
ret = mdp_out_if_register(&mdp->mdp_dev,
MSM_MDDI_PMDH_INTERFACE, mdp, MDP_DMA_P_DONE,
mdp_dma_to_mddi);
#endif
} else if (pdata->dma_channel == MDP_DMA_S) {
ret = mdp_out_if_register(&mdp->mdp_dev,
MSM_MDDI_PMDH_INTERFACE, mdp, MDP_DMA_S_DONE,
mdp_dmas_to_mddi);
}
#endif
if (ret)
goto error_mddi_pmdh_register;
@ -1019,13 +799,12 @@ int mdp_probe(struct platform_device *pdev)
goto error_get_mdp_clk;
}
mdp->ebi1_clk = clk_get(NULL, "ebi1_clk");
if (IS_ERR(mdp->ebi1_clk)) {
pr_err("mdp: failed to get ebi1 clk\n");
ret = PTR_ERR(mdp->ebi1_clk);
goto error_get_ebi1_clk;
}
mdp->ebi1_clk = clk_get(NULL, "ebi1_clk");
if (IS_ERR(mdp->ebi1_clk)) {
pr_err("mdp: failed to get ebi1 clk\n");
ret = PTR_ERR(mdp->ebi1_clk);
goto error_get_ebi1_clk;
}
ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
if (ret)
@ -1034,6 +813,7 @@ int mdp_probe(struct platform_device *pdev)
clk_enable(mdp->clk);
mdp_clk_to_disable_later = mdp->clk;
#ifdef CONFIG_MSM_MDP40
//MDP_DISP_INTF_SEL
if (mdp_readl(mdp, 0xc0000))
@ -1045,7 +825,6 @@ int mdp_probe(struct platform_device *pdev)
#endif
#ifdef CONFIG_MSM_MDP40
extern void mdp4_hw_init(struct mdp_info *mdp);
mdp4_hw_init(mdp);
#else
mdp_hw_init(mdp);
@ -1069,6 +848,10 @@ extern void mdp4_hw_init(struct mdp_info *mdp);
if (ret)
goto error_device_register;
setup_timer(&mdp->standby_timer, mdp_do_standby_timer, (unsigned long )mdp);
setup_timer(&mdp->dma_timer, mdp_do_dma_timer, (unsigned long )mdp);
pr_info("%s: initialized\n", __func__);
return 0;

View File

@ -47,12 +47,61 @@ struct mdp_info {
char * __iomem base;
int irq;
struct clk *clk;
struct clk *pclk;
struct clk *ebi1_clk;
struct mdp_out_interface out_if[MSM_MDP_NUM_INTERFACES];
int format;
int pack_pattern;
int dma_format;
int dma_pack_pattern;
bool dma_config_dirty;
struct mdp_blit_req *req;
uint32_t state;
struct timer_list standby_timer;
struct timer_list dma_timer;
int (*enable_irq)(struct mdp_info *mdp, uint32_t mask);
int (*disable_irq)(struct mdp_info *mdp, uint32_t mask);
};
struct mdp_lcdc_info {
struct mdp_info *mdp;
struct clk *mdp_clk;
struct clk *mdp_pclk;
struct clk *pclk;
struct clk *pad_pclk;
struct msm_panel_data fb_panel_data;
struct platform_device fb_pdev;
struct msm_lcdc_platform_data *pdata;
uint32_t fb_start;
struct msmfb_callback frame_start_cb;
wait_queue_head_t vsync_waitq;
int got_vsync;
unsigned color_format;
struct {
uint32_t clk_rate;
uint32_t hsync_ctl;
uint32_t vsync_period;
uint32_t vsync_pulse_width;
uint32_t display_hctl;
uint32_t display_vstart;
uint32_t display_vend;
uint32_t hsync_skew;
uint32_t polarity;
} parms;
atomic_t blank_count;
struct mutex blank_lock;
};
struct panel_icm_info {
bool icm_mode;
bool icm_doable;
bool clock_enabled;
int panel_update;
bool icm_suspend;
struct mutex icm_lock;
struct mdp_lcdc_info *lcdc;
spinlock_t lock;
void (*force_leave)(void);
};
extern int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
@ -64,15 +113,21 @@ extern int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
struct mdp_blit_req;
struct mdp_device;
int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start,
unsigned long src_len, struct file *dst_file,
unsigned long dst_start, unsigned long dst_len);
void mdp_ppp_dump_debug(const struct mdp_info *mdp);
int mdp_hw_init(struct mdp_info *mdp);
void mdp_check_tearing(struct mdp_info *mdp, struct msm_mdp_platform_data *pdata);
void mdp_dump_blit(struct mdp_blit_req *req);
int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq);
#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
#define mdp_readl(mdp, offset) readl(mdp->base + offset)
#define panel_to_lcdc(p) container_of((p), struct mdp_lcdc_info, fb_panel_data)
#define panel_to_dtv(p) container_of((p), struct mdp_dtv_info, fb_panel_data)
/* define mdp state for multi purpose */
#define MDP_STATE_STANDBY (1 << 0)
#ifdef CONFIG_MSM_MDP302
#define MDP_SYNC_CONFIG_0 ( 0x00300)
@ -142,6 +197,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
#define MDP_VSYNC_CTRL (0x0008c)
#define MDP_MDDI_PARAM_WR_SEL (0x00090)
#define MDP_MDDI_PARAM (0x00094)
#define MDP_MDDI_DATA_XFR (0x00098)
#define MDP_CGC_EN (0x00100)
#define MDP_CMD_STATUS (0x10008)
#define MDP_PROFILE_EN (0x10010)
@ -292,6 +348,21 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
#define MDP_LCDC_HSYNC_SKEW (0xc0030)
#define MDP_LCDC_TEST_CTL (0xc0034)
#define MDP_LCDC_CTL_POLARITY (0xc0038)
#define MDP_DTV_EN (0xd0000)
#define MDP_DTV_HSYNC_CTL (0xd0004)
#define MDP_DTV_VSYNC_PERIOD (0xd0008)
#define MDP_DTV_VSYNC_PULSE_WIDTH (0xd000c)
#define MDP_DTV_DISPLAY_HCTL (0xd0018)
#define MDP_DTV_DISPLAY_V_START (0xd001c)
#define MDP_DTV_DISPLAY_V_END (0xd0020)
#define MDP_DTV_ACTIVE_HCTL (0xd002c)
#define MDP_DTV_ACTIVE_V_START (0xd0030)
#define MDP_DTV_ACTIVE_V_END (0xd0038)
#define MDP_DTV_BORDER_CLR (0xd0040)
#define MDP_DTV_UNDERFLOW_CTL (0xd0044)
#define MDP_DTV_HSYNC_SKEW (0xd0048)
#define MDP_DTV_CTL_POLARITY (0xd0050)
#else
#define MDP_LCDC_EN (0xe0000)
#define MDP_LCDC_HSYNC_CTL (0xe0004)
@ -321,6 +392,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
#define TV_OUT_DMA3_DONE (1<<6)
#define TV_ENC_UNDERRUN (1<<7)
#define TV_OUT_FRAME_START (1<<13)
#define MDP_HIST_DONE (1<<20)
#ifdef CONFIG_MSM_MDP22
#define MDP_DMA_P_DONE (1 << 2)
@ -800,6 +872,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
#define DMA_PACK_LOOSE 0
#define DMA_PACK_ALIGN_LSB 0
#define DMA_PACK_ALIGN_MSB (1<<7)
#define DMA_PACK_ALIGN_MASK (1<<7)
#define DMA_PACK_PATTERN_MASK (0x3f<<8)
#define DMA_PACK_PATTERN_RGB \
(MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
@ -823,31 +896,14 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
#define DMA_IBUF_FORMAT_MASK (1 << 20)
#define DMA_IBUF_NONCONTIGUOUS (1<<21)
#elif defined(CONFIG_MSM_MDP30)
#define DMA_OUT_SEL_AHB 0
#define DMA_OUT_SEL_MDDI (1<<19)
#define DMA_AHBM_LCD_SEL_PRIMARY 0
#define DMA_AHBM_LCD_SEL_SECONDARY (0)
#define DMA_IBUF_C3ALPHA_EN (0)
#define DMA_DITHER_EN (1<<24)
#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (0)
#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (0)
#define DMA_IBUF_FORMAT_MASK (1 << 20)
#define DMA_IBUF_FORMAT_RGB565 (1<<25)
#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 (1<<26)
#define DMA_IBUF_NONCONTIGUOUS (0)
#else /* CONFIG_MSM_MDP31 | CONFIG_MSM_MDP302 */
#else /* CONFIG_MSM_MDP31 || CONFIG_MSM_MDP40 */
#define DMA_OUT_SEL_AHB (0 << 19)
#define DMA_OUT_SEL_MDDI (1 << 19)
#define DMA_OUT_SEL_LCDC (2 << 19)
#define DMA_OUT_SEL_LCDC_MDDI (3 << 19)
#define DMA_DITHER_EN (1 << 24)
#define DMA_DEFLKR_EN (1 << 24) /* dma_e */
#define DMA_IBUF_FORMAT_RGB888 (0 << 25)
#define DMA_IBUF_FORMAT_RGB565 (1 << 25)
#define DMA_IBUF_FORMAT_XRGB8888 (2 << 25)
@ -862,6 +918,7 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp);
/* MDDI REGISTER ? */
#define MDDI_VDO_PACKET_DESC_RGB565 0x5565
#define MDDI_VDO_PACKET_DESC_RGB666 0x5666
#define MDDI_VDO_PACKET_DESC_RGB888 0x5888
#define MDDI_VDO_PACKET_PRIM 0xC3
#define MDDI_VDO_PACKET_SECD 0xC0

View File

@ -0,0 +1,242 @@
/*
* Copyright (C) 2010 Google, Inc.
* Author: Dima Zavin <dima@android.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#include <linux/io.h>
#include "mdp_hw.h"
#include "mdp_ppp.h"
#include "mdp_csc_table.h"
#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
static unsigned int mdp_irq_mask;
#if 0
static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
uint32_t width, uint32_t height, uint32_t x,
uint32_t y)
{
struct mdp_info *mdp = priv;
uint32_t dma2_cfg;
uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
dma2_cfg = DMA_PACK_TIGHT |
DMA_PACK_ALIGN_LSB |
DMA_OUT_SEL_AHB |
DMA_IBUF_NONCONTIGUOUS;
dma2_cfg |= mdp->dma_format;
dma2_cfg |= mdp->dma_pack_pattern;
dma2_cfg |= DMA_OUT_SEL_MDDI;
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
dma2_cfg |= DMA_DITHER_EN;
/* 666 18BPP */
dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
#ifdef CONFIG_MSM_MDP22
/* setup size, address, and stride */
mdp_writel(mdp, (height << 16) | (width),
MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
/* set y & x offset and MDDI transaction parameters */
mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565)
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB565 << 16) | MDDI_VDO_PACKET_PRIM,
MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
else
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB666 << 16) | MDDI_VDO_PACKET_PRIM,
MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
/* start DMA2 */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
#else
/* setup size, address, and stride */
mdp_writel(mdp, (height << 16) | (width), MDP_DMA_P_SIZE);
mdp_writel(mdp, addr, MDP_DMA_P_IBUF_ADDR);
mdp_writel(mdp, stride, MDP_DMA_P_IBUF_Y_STRIDE);
/* set y & x offset and MDDI transaction parameters */
mdp_writel(mdp, (y << 16) | (x), MDP_DMA_P_OUT_XY);
mdp_writel(mdp, ld_param, MDP_MDDI_PARAM_WR_SEL);
if (mdp->mdp_dev.color_format == MSM_MDP_OUT_IF_FMT_RGB565)
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB565 << 16) | MDDI_VDO_PACKET_PRIM,
MDP_MDDI_PARAM);
else
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC_RGB666 << 16) | MDDI_VDO_PACKET_PRIM,
MDP_MDDI_PARAM);
mdp_writel(mdp, 0x1, MDP_MDDI_DATA_XFR);
mdp_writel(mdp, dma2_cfg, MDP_DMA_P_CONFIG);
mdp_writel(mdp, 0, MDP_DMA_P_START);
#endif
}
#endif
#if defined CONFIG_MSM_MDP302
void mdp_check_tearing(struct mdp_info *mdp, struct msm_mdp_platform_data *pdata)
{ mdp_writel(mdp, pdata->sync_config, MDP_SYNC_CONFIG_0);
mdp_writel(mdp, 1, MDP_TEAR_CHECK_EN);
mdp_writel(mdp, pdata->sync_thresh, MDP_SYNC_THRESH_0);
mdp_writel(mdp, pdata->sync_start_pos, MDP_PRIM_START_POS);
}
#endif
#if 0
int mdp_hw_init(struct mdp_info *mdp)
{
int n;
n = mdp_out_if_register(&mdp->mdp_dev, MSM_MDDI_PMDH_INTERFACE, mdp,
MDP_DMA_P_DONE, mdp_dma_to_mddi);
if (n)
return n;
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
/* debug interface write access */
mdp_writel(mdp, 1, 0x60);
mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
#ifndef CONFIG_MSM_MDP22
/* disable lcdc */
mdp_writel(mdp, 0, MDP_LCDC_EN);
/* enable auto clock gating for all blocks by default */
mdp_writel(mdp, 0xffffffff, MDP_CGC_EN);
/* reset color/gamma correct parms */
mdp_writel(mdp, 0, MDP_DMA_P_COLOR_CORRECT_CONFIG);
#endif
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
mdp_writel(mdp, 1, 0x60);
for (n = 0; n < ARRAY_SIZE(csc_color_lut); n++)
mdp_writel(mdp, csc_color_lut[n].val, csc_color_lut[n].reg);
/* clear up unused fg/main registers */
/* comp.plane 2&3 ystride */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
/* unpacked pattern */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
/* comp.plane 2 & 3 */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
/* clear unused bg registers */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
for (n = 0; n < ARRAY_SIZE(csc_matrix_config_table); n++)
mdp_writel(mdp, csc_matrix_config_table[n].val,
csc_matrix_config_table[n].reg);
mdp_ppp_init_scale(mdp);
#ifndef CONFIG_MSM_MDP31
mdp_writel(mdp, 0x04000400, MDP_COMMAND_CONFIG);
#endif
return 0;
}
#endif
int mdp_hw_init(struct mdp_info *mdp)
{
int n;
int lcdc_enabled;
mdp_irq_mask = 0;
mdp_writel(mdp, 0, MDP_INTR_ENABLE);
/* debug interface write access */
mdp_writel(mdp, 1, 0x60);
mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
#ifndef CONFIG_MSM_MDP22
lcdc_enabled = mdp_readl(mdp, MDP_LCDC_EN);
/* disable lcdc */
mdp_writel(mdp, 0, MDP_LCDC_EN);
/* enable auto clock gating for all blocks by default */
mdp_writel(mdp, 0xffffffff, MDP_CGC_EN);
/* reset color/gamma correct parms */
mdp_writel(mdp, 0, MDP_DMA_P_COLOR_CORRECT_CONFIG);
#endif
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
mdp_writel(mdp, 1, 0x60);
for (n = 0; n < ARRAY_SIZE(csc_color_lut); n++)
mdp_writel(mdp, csc_color_lut[n].val, csc_color_lut[n].reg);
/* clear up unused fg/main registers */
/* comp.plane 2&3 ystride */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
/* unpacked pattern */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
/* comp.plane 2 & 3 */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
/* clear unused bg registers */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
for (n = 0; n < ARRAY_SIZE(csc_matrix_config_table); n++)
mdp_writel(mdp, csc_matrix_config_table[n].val,
csc_matrix_config_table[n].reg);
mdp_ppp_init_scale(mdp);
#ifndef CONFIG_MSM_MDP31
mdp_writel(mdp, 0x04000400, MDP_COMMAND_CONFIG);
#endif
#ifndef CONFIG_MSM_MDP22
if (lcdc_enabled)
mdp_writel(mdp, 1, MDP_LCDC_EN);
#endif
return 0;
}

View File

@ -23,6 +23,7 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/mach-types.h>
@ -33,6 +34,9 @@
#ifdef CONFIG_MSM_MDP40
#include "mdp4.h"
#endif
#ifdef CONFIG_PANEL_SELF_REFRESH
#include <linux/kthread.h>
#endif
#if 0
#define D(fmt, args...) printk(KERN_INFO "Dispaly: " fmt, ##args)
@ -43,32 +47,6 @@
#if defined(CONFIG_ARCH_MSM7227)
#define LCDC_MUX_CTL (MSM_TGPIO1_BASE + 0x278)
#endif
struct mdp_lcdc_info {
struct mdp_info *mdp;
struct clk *mdp_clk;
struct clk *pclk;
struct clk *pad_pclk;
struct msm_panel_data fb_panel_data;
struct platform_device fb_pdev;
struct msm_lcdc_platform_data *pdata;
uint32_t fb_start;
struct msmfb_callback frame_start_cb;
wait_queue_head_t vsync_waitq;
int got_vsync;
unsigned color_format;
struct {
uint32_t clk_rate;
uint32_t hsync_ctl;
uint32_t vsync_period;
uint32_t vsync_pulse_width;
uint32_t display_hctl;
uint32_t display_vstart;
uint32_t display_vend;
uint32_t hsync_skew;
uint32_t polarity;
} parms;
};
static struct mdp_device *mdp_dev;
@ -76,7 +54,142 @@ static struct mdp_device *mdp_dev;
static struct mdp4_overlay_pipe *lcdc_pipe;
#endif
#define panel_to_lcdc(p) container_of((p), struct mdp_lcdc_info, fb_panel_data)
#ifdef CONFIG_PANEL_SELF_REFRESH
#if 0
#define ICM_DBG(s...) printk("[icm]" s)
#else
#define ICM_DBG(s...) do {} while (0)
#endif
/* set the timeout to 200 milliseconds */
#define PANEL_ENTER_IDLE_TIMEOUT HZ/5
/* Afetr setting ICM=1, we need to keep sending the RGB signal more than 2-frame */
#define PANEL_IDLE_STABLE_TIMEOUT 48
static struct task_struct *th_display;
struct panel_icm_info *panel_icm;
DECLARE_WAIT_QUEUE_HEAD(panel_update_wait_queue);
#endif
#ifdef CONFIG_PANEL_SELF_REFRESH
static int icm_check_panel_update(void)
{
int ret;
unsigned long irq_flags = 0;
spin_lock_irqsave(&panel_icm->lock, irq_flags);
ret = panel_icm->panel_update;
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
return ret;
}
static int icm_thread(void *data)
{
struct mdp_lcdc_info *lcdc;
struct msm_lcdc_panel_ops *panel_ops;
int rc;
unsigned long irq_flags = 0;
lcdc = data;
panel_ops = lcdc->pdata->panel_ops;
while (1) {
rc = wait_event_timeout(panel_update_wait_queue, icm_check_panel_update() == 1, PANEL_ENTER_IDLE_TIMEOUT);
ICM_DBG("ICM Thread:wake up rc=%d \n", rc);
mutex_lock(&panel_icm->icm_lock);
if (rc == 0 && icm_check_panel_update() != 1) {/* wait_timeout */
ICM_DBG("EnterICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
if (panel_icm->icm_mode == false && panel_icm->icm_doable == true) {
if (panel_ops->refresh_enable)
panel_ops->refresh_enable(panel_ops);
panel_icm->icm_mode = true;
msleep(PANEL_IDLE_STABLE_TIMEOUT);
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
clk_disable(lcdc->pad_pclk);
clk_disable(lcdc->pclk);
clk_disable(lcdc->mdp_clk);
panel_icm->clock_enabled = false;
pr_info("EnterICM: enter ICM MODE done!!!\n");
}
} else {/* get update event, no timeout */
ICM_DBG("Leave ICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
if (panel_icm->icm_mode == true && panel_icm->icm_doable == true) {
clk_enable(lcdc->mdp_clk);
clk_enable(lcdc->pclk);
clk_enable(lcdc->pad_pclk);
mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
panel_icm->clock_enabled = true;
if (panel_ops->refresh_disable)
panel_ops->refresh_disable(panel_ops);
panel_icm->icm_mode = false;
pr_info("LeaveICM: leave ICM MODE done !!!\n");
}
spin_lock_irqsave(&panel_icm->lock, irq_flags);
panel_icm->panel_update = 0;
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
}
mutex_unlock(&panel_icm->icm_lock);
} /* end while */
return 0;
}
static void icm_force_leave(void)
{
struct msm_lcdc_panel_ops *panel_ops;
unsigned long irq_flags = 0;
panel_ops = panel_icm->lcdc->pdata->panel_ops;
mutex_lock(&panel_icm->icm_lock);
ICM_DBG("Force Leave ICM: icm_mode=%d icm_doable=%d \n", panel_icm->icm_mode, panel_icm->icm_doable);
if (panel_icm->icm_mode == true) {
clk_enable(panel_icm->lcdc->mdp_clk);
clk_enable(panel_icm->lcdc->pclk);
clk_enable(panel_icm->lcdc->pad_pclk);
mdp_writel(panel_icm->lcdc->mdp, 1, MDP_LCDC_EN);
panel_icm->clock_enabled = true;
if (panel_ops->refresh_disable)
panel_ops->refresh_disable(panel_ops);
panel_icm->icm_mode = false;
panel_icm->icm_doable = true;
pr_info("ForceLeaveICM: leave ICM MODE done !!!\n");
}
spin_lock_irqsave(&panel_icm->lock, irq_flags);
panel_icm->panel_update = 0;
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
mutex_unlock(&panel_icm->icm_lock);
}
static int icm_init(struct mdp_lcdc_info *lcdc)
{
int ret = 0;
/* init panel_icm_info */
panel_icm = kzalloc(sizeof(struct panel_icm_info), GFP_KERNEL);
if (!panel_icm)
return -ENOMEM;
panel_icm->icm_doable = 1;
panel_icm->clock_enabled = true;
panel_icm->lcdc = lcdc;
panel_icm->force_leave = icm_force_leave;
panel_icm->icm_suspend = false;
mutex_init(&panel_icm->icm_lock);
th_display = kthread_run(icm_thread, lcdc, "panel-enterIdle");
if (IS_ERR(th_display)) {
ret = PTR_ERR(th_display);
pr_err("%s: panel_icm_thread create fail:%d!!!\n", __func__, ret);
goto error_create_thread;
}
return ret;
error_create_thread:
kfree(panel_icm);
return ret;
}
#endif
static int lcdc_unblank(struct msm_panel_data *fb_panel)
{
@ -85,7 +198,8 @@ static int lcdc_unblank(struct msm_panel_data *fb_panel)
pr_info("%s: ()\n", __func__);
panel_ops->unblank(panel_ops);
if (panel_ops->unblank)
panel_ops->unblank(panel_ops);
return 0;
}
@ -96,14 +210,28 @@ static int lcdc_blank(struct msm_panel_data *fb_panel)
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
pr_info("%s: ()\n", __func__);
panel_ops->blank(panel_ops);
if (panel_ops->blank)
panel_ops->blank(panel_ops);
return 0;
}
static int lcdc_shutdown(struct msm_panel_data *fb_panel)
{
struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
pr_info("%s: ()\n", __func__);
if (panel_ops->shutdown)
panel_ops->shutdown(panel_ops);
return 0;
}
static int lcdc_suspend(struct msm_panel_data *fb_panel)
{
int status;
struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
@ -111,13 +239,39 @@ static int lcdc_suspend(struct msm_panel_data *fb_panel)
#if defined(CONFIG_ARCH_MSM7227)
writel(0x0, LCDC_MUX_CTL);
status = readl(LCDC_MUX_CTL);
D("suspend_lcdc_mux_ctl = %x\n", status);
D("suspend_lcdc_mux_ctl = %x\n", readl(LCDC_MUX_CTL));
#endif
#ifdef CONFIG_PANEL_SELF_REFRESH
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
mutex_lock(&panel_icm->icm_lock);
panel_icm->icm_doable = false;
pr_info("[ICM %s]: icm mode=%d, clock_enabled=%d\n", __func__, panel_icm->icm_mode, panel_icm->clock_enabled);
if (panel_icm->icm_mode == true && panel_icm->clock_enabled == false) {
if (panel_ops->refresh_disable)
panel_ops->refresh_disable(panel_ops);
panel_icm->icm_mode = false;
} else {
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
clk_disable(lcdc->pad_pclk);
clk_disable(lcdc->pclk);
clk_disable(lcdc->mdp_clk);
}
panel_icm->clock_enabled = false;
mutex_unlock(&panel_icm->icm_lock);
} else {
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
clk_disable(lcdc->pad_pclk);
clk_disable(lcdc->pclk);
clk_disable(lcdc->mdp_clk);
}
#else
mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
clk_disable(lcdc->pad_pclk);
clk_disable(lcdc->pclk);
if (lcdc->mdp_pclk)
clk_disable(lcdc->mdp_pclk);
clk_disable(lcdc->mdp_clk);
#endif
if (panel_ops->uninit)
panel_ops->uninit(panel_ops);
@ -126,7 +280,6 @@ static int lcdc_suspend(struct msm_panel_data *fb_panel)
static int lcdc_resume(struct msm_panel_data *fb_panel)
{
unsigned int status;
struct mdp_lcdc_info *lcdc = panel_to_lcdc(fb_panel);
struct msm_lcdc_panel_ops *panel_ops = lcdc->pdata->panel_ops;
@ -136,17 +289,26 @@ static int lcdc_resume(struct msm_panel_data *fb_panel)
if (panel_ops->init(panel_ops) < 0)
printk(KERN_ERR "LCD init fail!\n");
}
clk_enable(lcdc->mdp_clk);
if (lcdc->mdp_pclk)
clk_enable(lcdc->mdp_pclk);
clk_enable(lcdc->pclk);
clk_enable(lcdc->pad_pclk);
#if defined(CONFIG_ARCH_MSM7227)
writel(0x1, LCDC_MUX_CTL);
status = readl(LCDC_MUX_CTL);
D("resume_lcdc_mux_ctl = %x\n",status);
D("resume_lcdc_mux_ctl = %x\n", readl(LCDC_MUX_CTL));
#endif
mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
#ifdef CONFIG_PANEL_SELF_REFRESH
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
mutex_lock(&panel_icm->icm_lock);
panel_icm->icm_doable = true;
panel_icm->clock_enabled = true;
panel_icm->icm_suspend = false;
mutex_unlock(&panel_icm->icm_lock);
}
#endif
return 0;
}
@ -157,12 +319,13 @@ static int lcdc_hw_init(struct mdp_lcdc_info *lcdc)
uint32_t dma_cfg;
clk_enable(lcdc->mdp_clk);
if (lcdc->mdp_pclk)
clk_enable(lcdc->mdp_pclk);
clk_enable(lcdc->pclk);
clk_enable(lcdc->pad_pclk);
clk_set_rate(lcdc->pclk, lcdc->parms.clk_rate);
clk_set_rate(lcdc->pad_pclk, lcdc->parms.clk_rate);
/* write the lcdc params */
mdp_writel(lcdc->mdp, lcdc->parms.hsync_ctl, MDP_LCDC_HSYNC_CTL);
mdp_writel(lcdc->mdp, lcdc->parms.vsync_period, MDP_LCDC_VSYNC_PERIOD);
@ -175,46 +338,45 @@ static int lcdc_hw_init(struct mdp_lcdc_info *lcdc)
mdp_writel(lcdc->mdp, lcdc->parms.hsync_skew, MDP_LCDC_HSYNC_SKEW);
mdp_writel(lcdc->mdp, 0, MDP_LCDC_BORDER_CLR);
mdp_writel(lcdc->mdp, 0xff, MDP_LCDC_UNDERFLOW_CTL);
mdp_writel(lcdc->mdp, 0x80000000 | 0xff, MDP_LCDC_UNDERFLOW_CTL);
mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_HCTL);
mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_START);
mdp_writel(lcdc->mdp, 0, MDP_LCDC_ACTIVE_V_END);
mdp_writel(lcdc->mdp, lcdc->parms.polarity, MDP_LCDC_CTL_POLARITY);
/* config the dma_p block that drives the lcdc data */
mdp_writel(lcdc->mdp, lcdc->fb_start, MDP_DMA_P_IBUF_ADDR);
mdp_writel(lcdc->mdp, (((fb_panel->fb_data->yres & 0x7ff) << 16) |
(fb_panel->fb_data->xres & 0x7ff)),
MDP_DMA_P_SIZE);
mdp_writel(lcdc->mdp, 0, MDP_DMA_P_OUT_XY);
dma_cfg = mdp_readl(lcdc->mdp, MDP_DMA_P_CONFIG);
#if defined(CONFIG_MACH_HTCLEO)
dma_cfg &= ~(DMA_PACK_PATTERN_MASK | DMA_PACK_ALIGN_MASK);
dma_cfg |= (DMA_PACK_ALIGN_MSB |
DMA_PACK_PATTERN_RGB |
DMA_DITHER_EN);
DMA_PACK_PATTERN_RGB |
DMA_DITHER_EN);
dma_cfg |= DMA_OUT_SEL_LCDC;
dma_cfg |= DMA_IBUF_FORMAT_RGB565;
//dma_cfg &= ~DMA_DITHER_EN; // solve color banding issue - marc1706
//zeusk: dma_cfg |= DMA_IBUF_FORMAT_RGB565;
dma_cfg &= ~DMA_DST_BITS_MASK;
#else
dma_cfg |= (DMA_PACK_ALIGN_LSB |
DMA_PACK_PATTERN_RGB |
DMA_DITHER_EN);
dma_cfg |= DMA_OUT_SEL_LCDC;
dma_cfg &= ~DMA_DST_BITS_MASK;
#endif
if(lcdc->color_format == MSM_MDP_OUT_IF_FMT_RGB565)
dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
else if (lcdc->color_format == MSM_MDP_OUT_IF_FMT_RGB666)
dma_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
if (fb_panel->fb_data->output_format == MSM_MDP_OUT_IF_FMT_RGB666)
dma_cfg |= DMA_DSTC0G_6BITS |
DMA_DSTC1B_6BITS |
DMA_DSTC2R_6BITS;
else if (fb_panel->fb_data->output_format == MSM_MDP_OUT_IF_FMT_RGB888)
dma_cfg |= DMA_DSTC0G_8BITS |
DMA_DSTC1B_8BITS |
DMA_DSTC2R_8BITS;
else
dma_cfg |= DMA_DSTC0G_6BITS |
DMA_DSTC1B_5BITS |
DMA_DSTC2R_5BITS;
mdp_writel(lcdc->mdp, dma_cfg, MDP_DMA_P_CONFIG);
/* enable the lcdc timing generation */
mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
return 0;
}
@ -301,35 +463,6 @@ static void lcdc_dma_start(void *priv, uint32_t addr, uint32_t stride,
mdp_writel(lcdc->mdp, addr, MDP_DMA_P_IBUF_ADDR);
}
#ifdef CONFIG_MSM_MDP40
static void lcdc_overlay_start(void *priv, uint32_t addr, uint32_t stride,
uint32_t width, uint32_t height, uint32_t x,
uint32_t y)
{
struct mdp_lcdc_info *lcdc = priv;
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
struct mdp4_overlay_pipe *pipe;
pipe = lcdc_pipe;
pipe->srcp0_addr = addr;
if (mdp->dma_config_dirty)
{
if(mdp->format == DMA_IBUF_FORMAT_RGB565) {
pipe->src_format = MDP_RGB_565;
pipe->srcp0_ystride = pipe->src_width * 2;
} else if(mdp->format == DMA_IBUF_FORMAT_XRGB8888) {
pipe->src_format = MDP_RGBA_8888;
pipe->srcp0_ystride = pipe->src_width * 4;
}
mdp4_overlay_format2pipe(pipe);
mdp->dma_config_dirty = false;
}
mdp4_overlay_rgb_setup(pipe);
mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
}
#endif
static void precompute_timing_parms(struct mdp_lcdc_info *lcdc)
{
struct msm_lcdc_timing *timing = lcdc->pdata->timing;
@ -404,6 +537,10 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
goto err_get_mdp_clk;
}
lcdc->mdp_pclk = clk_get(mdp_dev->dev.parent, "mdp_pclk");
if (IS_ERR(lcdc->mdp_pclk))
lcdc->mdp_pclk = NULL;
lcdc->pclk = clk_get(mdp_dev->dev.parent, "lcdc_pclk_clk");
if (IS_ERR(lcdc->pclk)) {
pr_err("%s: failed to get lcdc_pclk\n", __func__);
@ -443,7 +580,10 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
if (lcdc_pipe == NULL) {
ptype = mdp4_overlay_format2type(MDP_RGB_565);
pipe = mdp4_overlay_pipe_alloc(ptype);
if (!pipe)
goto err_mdp4_overlay_pipe_alloc;
pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
pipe->pipe_used = 1;
pipe->mixer_num = MDP4_MIXER0;
pipe->src_format = MDP_RGB_565;
mdp4_overlay_format2pipe(pipe);
@ -463,15 +603,8 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
pipe->srcp0_addr = (uint32_t) lcdc->fb_start;
pipe->srcp0_ystride = pdata->fb_data->xres * 2;
mdp4_overlay_dmap_xy(pipe);
mdp4_overlay_dmap_cfg(pipe, 1);
mdp4_overlay_rgb_setup(pipe);
mdp4_mixer_stage_up(pipe);
mdp4_overlayproc_cfg(pipe);
mdp4_overlay_reg_flush(pipe, 1);
#endif
lcdc->fb_panel_data.suspend = lcdc_suspend;
@ -483,13 +616,12 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
lcdc->fb_panel_data.unblank = lcdc_unblank;
lcdc->fb_panel_data.fb_data = pdata->fb_data;
lcdc->fb_panel_data.interface_type = MSM_LCDC_INTERFACE;
lcdc->fb_panel_data.shutdown = lcdc_shutdown;
ret = lcdc_hw_init(lcdc);
if (ret) {
pr_err("%s: Cannot initialize the mdp_lcdc\n", __func__);
goto err_hw_init;
}
lcdc->fb_pdev.name = "msm_panel";
lcdc->fb_pdev.id = pdata->fb_id;
lcdc->fb_pdev.resource = pdata->fb_resource;
@ -504,16 +636,30 @@ static int mdp_lcdc_probe(struct platform_device *pdev)
}
pr_info("%s: initialized\n", __func__);
#ifdef CONFIG_PANEL_SELF_REFRESH
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
ret = icm_init(lcdc);
if (ret) {
pr_err("%s: Cannot init dispaly selfrefresh \n", __func__);
goto err_plat_dev_reg;
}
}
#endif
return 0;
err_plat_dev_reg:
err_hw_init:
#ifdef CONFIG_MSM_MDP40
err_mdp4_overlay_pipe_alloc:
#endif
platform_set_drvdata(pdev, NULL);
clk_put(lcdc->pad_pclk);
err_get_pad_pclk:
clk_put(lcdc->pclk);
err_get_pclk:
if (lcdc->mdp_pclk)
clk_put(lcdc->mdp_pclk);
clk_put(lcdc->mdp_clk);
err_get_mdp_clk:
kfree(lcdc);

View File

@ -15,8 +15,12 @@
#include <linux/fb.h>
#include <linux/file.h>
#include <linux/delay.h>
#include <linux/major.h>
#include <linux/msm_hw3d.h>
#include <linux/msm_mdp.h>
#include <linux/mutex.h>
#include <linux/android_pmem.h>
#include <linux/wait.h>
#include <mach/msm_fb.h>
#include "mdp_hw.h"
@ -52,19 +56,19 @@ static uint32_t dst_img_cfg[] = {
PPP_ARRAY1(CFG, DST)
};
static uint32_t bytes_per_pixel[] = {
static const uint32_t bytes_per_pixel[] = {
[MDP_RGB_565] = 2,
[MDP_RGB_888] = 3,
[MDP_XRGB_8888] = 4,
[MDP_Y_CBCR_H2V2] = 1,
[MDP_ARGB_8888] = 4,
[MDP_RGB_888] = 3,
[MDP_Y_CRCB_H2V2] = 1,
[MDP_YCRYCB_H2V1] = 2,
[MDP_Y_CRCB_H2V1] = 1,
[MDP_Y_CBCR_H2V1] = 1,
[MDP_RGBA_8888] = 4,
[MDP_BGRA_8888] = 4,
[MDP_RGBX_8888] = 4,
[MDP_Y_CBCR_H2V1] = 1,
[MDP_Y_CBCR_H2V2] = 1,
[MDP_Y_CRCB_H2V1] = 1,
[MDP_Y_CRCB_H2V2] = 1,
[MDP_YCRYCB_H2V1] = 2
};
static uint32_t dst_op_chroma[] = {
@ -79,6 +83,9 @@ static uint32_t bg_op_chroma[] = {
PPP_ARRAY1(CHROMA_SAMP, BG)
};
static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
DEFINE_MUTEX(mdp_mutex);
static uint32_t get_luma_offset(struct mdp_img *img,
struct mdp_rect *rect, uint32_t bpp)
{
@ -268,7 +275,6 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
req->alpha &= 0xff;
/* ALPHA BLEND */
if (HAS_ALPHA(req->src.format)) {
#if !defined(CONFIG_MACH_HTCLEO)
regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON;
if (req->flags & MDP_BLEND_FG_PREMULT) {
#ifdef CONFIG_MSM_MDP31
@ -285,10 +291,6 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
} else {
regs->op |= PPP_OP_BLEND_SRCPIXEL_ALPHA;
}
#else
regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON;
regs->op |= PPP_OP_BLEND_SRCPIXEL_ALPHA;
#endif
} else if (req->alpha < MDP_ALPHA_NOP) {
/* just blend by alpha */
regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
@ -309,7 +311,7 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
set_blend_region(&req->dst, &req->dst_rect, regs);
}
static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
static int blit_scale(struct mdp_info *mdp, struct mdp_blit_req *req,
struct ppp_regs *regs)
{
struct mdp_rect dst_rect;
@ -330,7 +332,7 @@ static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
}
if (mdp_ppp_cfg_scale(mdp, regs, &req->src_rect, &dst_rect,
req->src.format, req->dst.format)) {
req->src.format, req->dst.format)) {
DLOG("crap, bad scale\n");
return -1;
}
@ -339,7 +341,7 @@ static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
return 0;
}
static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
static void blit_blur(struct mdp_info *mdp, struct mdp_blit_req *req,
struct ppp_regs *regs)
{
int ret;
@ -411,21 +413,23 @@ static void flush_imgs(struct mdp_blit_req *req, struct ppp_regs *regs,
#ifdef CONFIG_ANDROID_PMEM
uint32_t src0_len, src1_len, dst0_len, dst1_len;
/* flush src images to memory before dma to mdp */
get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
&src1_len);
flush_pmem_file(src_file, req->src.offset, src0_len);
if (IS_PSEUDOPLNR(req->src.format))
flush_pmem_file(src_file, req->src.offset + src0_len,
src1_len);
if (!(req->flags & MDP_BLIT_NON_CACHED)) {
/* flush src images to memory before dma to mdp */
get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
&src1_len);
flush_pmem_file(src_file, req->src.offset, src0_len);
if (IS_PSEUDOPLNR(req->src.format))
flush_pmem_file(src_file, req->src.offset + src0_len,
src1_len);
/* flush dst images */
get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
&dst1_len);
flush_pmem_file(dst_file, req->dst.offset, dst0_len);
if (IS_PSEUDOPLNR(req->dst.format))
flush_pmem_file(dst_file, req->dst.offset + dst0_len,
dst1_len);
/* flush dst images */
get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
&dst1_len);
flush_pmem_file(dst_file, req->dst.offset, dst0_len);
if (IS_PSEUDOPLNR(req->dst.format))
flush_pmem_file(dst_file, req->dst.offset + dst0_len,
dst1_len);
}
#endif
}
@ -439,6 +443,13 @@ static uint32_t get_chroma_base(struct mdp_img *img, uint32_t base,
return addr;
}
int mdp_get_bytes_per_pixel(int format)
{
if (format < 0 || format >= MDP_IMGTYPE_LIMIT)
return -1;
return bytes_per_pixel[format];
}
#if PPP_DUMP_BLITS
#define mdp_writel_dbg(mdp, val, reg) do { \
pr_info("%s: writing 0x%08x=0x%08x\n", __func__, (reg), (val));\
@ -501,19 +512,17 @@ static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
mdp_writel_dbg(mdp, regs->bg_img_sz, MDP_PPP_BG_IMAGE_SIZE);
mdp_writel_dbg(mdp, regs->bg_alpha_sel,
MDP_PPP_BLEND_BG_ALPHA_SEL);
#if defined(CONFIG_MACH_HTCLEO)
#if 0 /* zeusk: defined(CONFIG_MACH_HTCLEO) */
mdp_writel_dbg(mdp, 0, MDP_TFETCH_TEST_MODE);
#endif
#endif
}
if( src_file != -1 && dst_file != -1 )
flush_imgs(req, regs, src_file, dst_file);
flush_imgs(req, regs, src_file, dst_file);
mdp_writel_dbg(mdp, 0x1000, MDP_DISPLAY0_START);
return 0;
}
void mdp_dump_blit(struct mdp_blit_req *req)
/*
static void mdp_dump_blit(struct mdp_blit_req *req)
{
pr_info("%s: src: w=%d h=%d f=0x%x offs=0x%x mem_id=%d\n", __func__,
req->src.width, req->src.height, req->src.format,
@ -531,8 +540,8 @@ void mdp_dump_blit(struct mdp_blit_req *req)
pr_info("%s: transp_max=0x%08x\n", __func__, req->transp_mask);
pr_info("%s: flags=%08x\n", __func__, req->flags);
}
int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
*/
static int process_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
{
@ -644,13 +653,6 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
return 0;
}
int mdp_get_bytes_per_pixel(int format)
{
if (format < 0 || format >= MDP_IMGTYPE_LIMIT)
return -1;
return bytes_per_pixel[format];
}
#define mdp_dump_register(mdp, reg) \
printk(# reg ": %08x\n", mdp_readl((mdp), (reg)))
@ -668,234 +670,164 @@ void mdp_ppp_dump_debug(const struct mdp_info *mdp)
mdp_dump_register(mdp, MDP_INTR_ENABLE);
}
/* Splits a blit into two horizontal stripes. Used to work around MDP bugs */
int mdp_ppp_blit_split_height(struct mdp_info *mdp, const struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
static int mdp_ppp_wait(struct mdp_info *mdp)
{
int ret;
struct mdp_blit_req splitreq;
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
splitreq = *req;
/* break dest roi at height*/
d_x_0 = d_x_1 = req->dst_rect.x;
d_w_0 = d_w_1 = req->dst_rect.w;
d_y_0 = req->dst_rect.y;
if (req->dst_rect.h % 32 == 3)
d_h_1 = (req->dst_rect.h - 3) / 2 - 1;
else
d_h_1 = (req->dst_rect.h - 1) / 2 - 1;
d_h_0 = req->dst_rect.h - d_h_1;
d_y_1 = d_y_0 + d_h_0;
if (req->dst_rect.h == 3) {
d_h_1 = 2;
d_h_0 = 2;
d_y_1 = d_y_0 + 1;
}
/* break source roi */
if (splitreq.flags & MDP_ROT_90) {
s_y_0 = s_y_1 = req->src_rect.y;
s_h_0 = s_h_1 = req->src_rect.h;
s_x_0 = req->src_rect.x;
s_w_1 = (req->src_rect.w * d_h_1) / req->dst_rect.h;
s_w_0 = req->src_rect.w - s_w_1;
s_x_1 = s_x_0 + s_w_0;
if (d_h_1 >= 8 * s_w_1) {
s_w_1++;
s_x_1--;
}
} else {
s_x_0 = s_x_1 = req->src_rect.x;
s_w_0 = s_w_1 = req->src_rect.w;
s_y_0 = req->src_rect.y;
s_h_1 = (req->src_rect.h * d_h_1) / req->dst_rect.h;
s_h_0 = req->src_rect.h - s_h_1;
s_y_1 = s_y_0 + s_h_0;
if (d_h_1 >= 8 * s_h_1) {
s_h_1++;
s_y_1--;
}
}
/* blit first region */
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_90) ||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
} else {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
}
ret = mdp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
ret = mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
if (ret)
return ret;
/* blit second region */
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_90) ||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
} else {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
}
ret = mdp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
mdp_ppp_dump_debug(mdp);
return ret;
}
/* Splits a blit into two vertical stripes. Used to work around MDP bugs */
int mdp_ppp_blit_split_width(struct mdp_info *mdp, const struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
static int get_img(struct mdp_img *img, struct fb_info *info,
unsigned long *start, unsigned long *len,
struct file** filep)
{
int put_needed, ret = 0;
struct file *file;
unsigned long vstart;
if (img->memory_id & 0x40000000)
{
struct fb_info *fb = registered_fb[img->memory_id & 0x0000FFFF];
if (fb)
{
*start = fb->fix.smem_start;
*len = fb->fix.smem_len;
}
*filep = NULL;
return 0;
}
if (!get_pmem_file(img->memory_id, start, &vstart, len, filep))
return 0;
else if (!get_msm_hw3d_file(img->memory_id, &img->offset, start, len,
filep))
return 0;
file = fget_light(img->memory_id, &put_needed);
if (file == NULL)
return -1;
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
*start = info->fix.smem_start;
*len = info->fix.smem_len;
ret = 0;
} else
ret = -1;
fput_light(file, put_needed);
return ret;
}
void put_img(struct file *p_src_file)
{
#ifdef CONFIG_ANDROID_PMEM
if (p_src_file)
put_pmem_file(p_src_file);
#else
if (is_msm_hw3d_file(p_src_file))
put_msm_hw3d_file(p_src_file);
#endif
}
static void dump_req(struct mdp_blit_req *req,
unsigned long src_start, unsigned long src_len,
unsigned long dst_start, unsigned long dst_len)
{
pr_err("flags: 0x%x\n", req->flags);
pr_err("src_start: 0x%08lx\n", src_start);
pr_err("src_len: 0x%08lx\n", src_len);
pr_err("src.offset: 0x%x\n", req->src.offset);
pr_err("src.format: 0x%x\n", req->src.format);
pr_err("src.width: %d\n", req->src.width);
pr_err("src.height: %d\n", req->src.height);
pr_err("src_rect.x: %d\n", req->src_rect.x);
pr_err("src_rect.y: %d\n", req->src_rect.y);
pr_err("src_rect.w: %d\n", req->src_rect.w);
pr_err("src_rect.h: %d\n", req->src_rect.h);
pr_err("dst_start: 0x%08lx\n", dst_start);
pr_err("dst_len: 0x%08lx\n", dst_len);
pr_err("dst.offset: 0x%x\n", req->dst.offset);
pr_err("dst.format: 0x%x\n", req->dst.format);
pr_err("dst.width: %d\n", req->dst.width);
pr_err("dst.height: %d\n", req->dst.height);
pr_err("dst_rect.x: %d\n", req->dst_rect.x);
pr_err("dst_rect.y: %d\n", req->dst_rect.y);
pr_err("dst_rect.w: %d\n", req->dst_rect.w);
pr_err("dst_rect.h: %d\n", req->dst_rect.h);
}
int mdp_ppp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
{
int ret;
struct mdp_blit_req splitreq;
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
splitreq = *req;
/* break dest roi at width*/
d_y_0 = d_y_1 = req->dst_rect.y;
d_h_0 = d_h_1 = req->dst_rect.h;
d_x_0 = req->dst_rect.x;
if (req->dst_rect.w % 32 == 6)
d_w_1 = req->dst_rect.w / 2 - 1;
else if (req->dst_rect.w % 2 == 0)
d_w_1 = req->dst_rect.w / 2;
else if (req->dst_rect.w % 32 == 3)
d_w_1 = (req->dst_rect.w - 3) / 2 - 1;
else
d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
d_w_0 = req->dst_rect.w - d_w_1;
d_x_1 = d_x_0 + d_w_0;
if (req->dst_rect.w == 3) {
d_w_1 = 2;
d_w_0 = 2;
d_x_1 = d_x_0 + 1;
mdp->enable_irq(mdp, DL0_ROI_DONE);
ret = process_blit(mdp, req, src_file, src_start, src_len,
dst_file, dst_start, dst_len);
if (unlikely(ret)) {
mdp->disable_irq(mdp, DL0_ROI_DONE);
return ret;
}
/* break src roi at height or width*/
if (splitreq.flags & MDP_ROT_90) {
s_x_0 = s_x_1 = req->src_rect.x;
s_w_0 = s_w_1 = req->src_rect.w;
s_y_0 = req->src_rect.y;
s_h_1 = (req->src_rect.h * d_w_1) / req->dst_rect.w;
s_h_0 = req->src_rect.h - s_h_1;
s_y_1 = s_y_0 + s_h_0;
if (d_w_1 >= 8 * s_h_1) {
s_h_1++;
s_y_1--;
}
} else {
s_y_0 = s_y_1 = req->src_rect.y;
s_h_0 = s_h_1 = req->src_rect.h;
s_x_0 = req->src_rect.x;
s_w_1 = (req->src_rect.w * d_w_1) / req->dst_rect.w;
s_w_0 = req->src_rect.w - s_w_1;
s_x_1 = s_x_0 + s_w_0;
if (d_w_1 >= 8 * s_w_1) {
s_w_1++;
s_x_1--;
}
ret = mdp_ppp_wait(mdp);
if (unlikely(ret)) {
printk(KERN_ERR "%s: failed!\n", __func__);
pr_err("original request:\n");
dump_req(mdp->req, src_start, src_len, dst_start, dst_len);
pr_err("dead request:\n");
dump_req(req, src_start, src_len, dst_start, dst_len);
BUG();
return ret;
}
return 0;
}
/* blit first region */
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_270) ||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
} else {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
}
int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
struct mdp_blit_req *req)
{
int ret;
unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
struct file *src_file = 0, *dst_file = 0;
if (unlikely((splitreq.dst_rect.h != 1) &&
((splitreq.dst_rect.h % 32 == 3) ||
(splitreq.dst_rect.h % 32) == 1)))
ret = mdp_ppp_blit_split_height(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
else
ret = mdp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
ret = mdp_ppp_validate_blit(mdp, req);
if (ret)
return ret;
/* blit second region */
if (((splitreq.flags & MDP_ROT_MASK) == MDP_ROT_270) ||
((splitreq.flags & MDP_ROT_MASK) == 0x0)) {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
} else {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
/* do this first so that if this fails, the caller can always
* safely call put_img */
if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
printk(KERN_ERR "mdp_ppp: could not retrieve src image from "
"memory\n");
return -EINVAL;
}
if (unlikely((splitreq.dst_rect.h != 1) &&
((splitreq.dst_rect.h % 32 == 3) ||
(splitreq.dst_rect.h % 32) == 1)))
ret = mdp_ppp_blit_split_height(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
else
ret = mdp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
printk(KERN_ERR "mdp_ppp: could not retrieve dst image from "
"memory\n");
put_img(src_file);
return -EINVAL;
}
mutex_lock(&mdp_mutex);
/* transp_masking unimplemented */
req->transp_mask = MDP_TRANSP_NOP;
mdp->req = req;
ret = mdp_ppp_do_blit(mdp, req, src_file, src_start, src_len,
dst_file, dst_start, dst_len);
put_img(src_file);
put_img(dst_file);
mutex_unlock(&mdp_mutex);
return ret;
}
}
void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask)
{
if (mask & DL0_ROI_DONE)
wake_up(&mdp_ppp_waitqueue);
}

View File

@ -16,7 +16,6 @@
#define _VIDEO_MSM_MDP_PPP_H_
#include <linux/types.h>
#define PPP_DUMP_BLITS 0
struct ppp_regs {
uint32_t src0;
@ -63,40 +62,57 @@ struct ppp_regs {
struct mdp_info;
struct mdp_rect;
struct mdp_blit_req;
struct fb_info;
void mdp_ppp_init_scale(const struct mdp_info *mdp);
int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
uint32_t src_format, uint32_t dst_format);
int mdp_ppp_load_blur(const struct mdp_info *mdp);
void mdp_dump_blit(struct mdp_blit_req *req);
#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP302)
int mdp_ppp_blit_split_width(struct mdp_info *mdp, const struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len);
int mdp_ppp_blit_split_height(struct mdp_info *mdp, const struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len);
#if defined(CONFIG_MSM_MDP302)
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
#else
static inline int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req,
struct ppp_regs *regs)
{
return 0;
}
#endif
#else
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
#endif
#ifdef CONFIG_FB_MSM_MDP_PPP
int mdp_get_bytes_per_pixel(int format);
int mdp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len);
int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
struct mdp_blit_req *req);
void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask);
int mdp_ppp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start,
unsigned long src_len, struct file *dst_file,
unsigned long dst_start, unsigned long dst_len);
/* these must be provided by h/w specific ppp files */
void mdp_ppp_init_scale(struct mdp_info *mdp);
int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
uint32_t src_format, uint32_t dst_format);
int mdp_ppp_load_blur(struct mdp_info *mdp);
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req);
int mdp_ppp_do_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start,
unsigned long src_len, struct file *dst_file,
unsigned long dst_start, unsigned long dst_len);
#else
static inline int mdp_get_bytes_per_pixel(int format) { return -1; }
static inline int mdp_ppp_blit(struct mdp_info *mdp, struct fb_info *fb,
struct mdp_blit_req *req) { return -EINVAL; }
static inline void mdp_ppp_handle_isr(struct mdp_info *mdp, uint32_t mask) {}
static inline int mdp_ppp_blit_and_wait(struct mdp_info *mdp,
struct mdp_blit_req *req, struct file *src_file,
unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start,
unsigned long dst_len) { return 0; }
static inline void mdp_ppp_init_scale(struct mdp_info *mdp) {}
static inline int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
uint32_t src_format, uint32_t dst_format) { return 0; }
static inline int mdp_ppp_load_blur(struct mdp_info *mdp) { return 0; }
static inline int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs) { return 0; }
static inline int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req) { return -EINVAL; }
static inline int mdp_ppp_do_blit(struct mdp_info *mdp,
struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start,
unsigned long src_len, struct file *dst_file,
unsigned long dst_start, unsigned long dst_len) { return 0; }
#endif /* CONFIG_FB_MSM_MDP_PPP */
#endif /* _VIDEO_MSM_MDP_PPP_H_ */

View File

@ -1016,7 +1016,7 @@ static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
return 0;
}
int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
uint32_t src_format, uint32_t dst_format)
{
@ -1070,7 +1070,7 @@ int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
}
int mdp_ppp_load_blur(const struct mdp_info *mdp)
int mdp_ppp_load_blur(struct mdp_info *mdp)
{
if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
downscale_y_table == MDP_DOWNSCALE_BLUR)) {
@ -1082,10 +1082,64 @@ int mdp_ppp_load_blur(const struct mdp_info *mdp)
return 0;
}
void mdp_ppp_init_scale(const struct mdp_info *mdp)
void mdp_ppp_init_scale(struct mdp_info *mdp)
{
downscale_x_table = MDP_DOWNSCALE_MAX;
downscale_y_table = MDP_DOWNSCALE_MAX;
load_table(mdp, mdp_upscale_table, ARRAY_SIZE(mdp_upscale_table));
}
int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req)
{
/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
if (unlikely(req->src_rect.h == 0 ||
req->src_rect.w == 0)) {
pr_info("mdp_ppp: src img of zero size!\n");
return -EINVAL;
}
if (unlikely(req->dst_rect.h == 0 ||
req->dst_rect.w == 0))
return -EINVAL;
return 0;
}
int mdp_ppp_do_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start,
unsigned long src_len, struct file *dst_file,
unsigned long dst_start, unsigned long dst_len)
{
int ret;
if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
req->alpha != MDP_ALPHA_NOP ||
HAS_ALPHA(req->src.format)) &&
(req->flags & MDP_ROT_90 &&
req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
int i;
unsigned int tiles = req->dst_rect.h / 16;
unsigned int remainder = req->dst_rect.h % 16;
req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
req->dst_rect.h = 16;
for (i = 0; i < tiles; i++) {
ret = mdp_ppp_blit_and_wait(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
if (ret)
goto end;
req->dst_rect.y += 16;
req->src_rect.x += req->src_rect.w;
}
if (!remainder)
goto end;
req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
req->dst_rect.h = remainder;
}
ret = mdp_ppp_blit_and_wait(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
end:
return ret;
}

View File

@ -276,7 +276,7 @@ static int scale_idx(int factor)
return idx;
}
int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
int mdp_ppp_cfg_scale(struct mdp_info *mdp, struct ppp_regs *regs,
struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
uint32_t src_format, uint32_t dst_format)
{
@ -319,16 +319,319 @@ int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
return 0;
}
int mdp_ppp_load_blur(const struct mdp_info *mdp)
int mdp_ppp_load_blur(struct mdp_info *mdp)
{
return -ENOTSUPP;
}
void mdp_ppp_init_scale(const struct mdp_info *mdp)
int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
{
return 0;
}
void mdp_ppp_init_scale(struct mdp_info *mdp)
{
int scale;
for (scale = 0; scale < MDP_SCALE_MAX; ++scale)
load_table(mdp, scale, 0);
}
/* Splits a blit into two horizontal stripes. Used to work around MDP bugs */
static int blit_split_height(struct mdp_info *mdp, const struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
{
int ret;
struct mdp_blit_req splitreq;
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
splitreq = *req;
/* break dest roi at height*/
d_x_0 = d_x_1 = req->dst_rect.x;
d_w_0 = d_w_1 = req->dst_rect.w;
d_y_0 = req->dst_rect.y;
if (req->dst_rect.h % 32 == 3)
d_h_1 = (req->dst_rect.h - 3) / 2 - 1;
else
d_h_1 = (req->dst_rect.h - 1) / 2 - 1;
d_h_0 = req->dst_rect.h - d_h_1;
d_y_1 = d_y_0 + d_h_0;
if (req->dst_rect.h == 3) {
d_h_1 = 2;
d_h_0 = 2;
d_y_1 = d_y_0 + 1;
}
/* break source roi */
if (splitreq.flags & MDP_ROT_90) {
s_y_0 = s_y_1 = req->src_rect.y;
s_h_0 = s_h_1 = req->src_rect.h;
s_x_0 = req->src_rect.x;
s_w_1 = (req->src_rect.w * d_h_1) / req->dst_rect.h;
s_w_0 = req->src_rect.w - s_w_1;
s_x_1 = s_x_0 + s_w_0;
if (d_h_1 >= 8 * s_w_1) {
s_w_1++;
s_x_1--;
}
} else {
s_x_0 = s_x_1 = req->src_rect.x;
s_w_0 = s_w_1 = req->src_rect.w;
s_y_0 = req->src_rect.y;
s_h_1 = (req->src_rect.h * d_h_1) / req->dst_rect.h;
s_h_0 = req->src_rect.h - s_h_1;
s_y_1 = s_y_0 + s_h_0;
if (d_h_1 >= 8 * s_h_1) {
s_h_1++;
s_y_1--;
}
}
/* blit first region */
if (((splitreq.flags & 0x07) == MDP_ROT_90) ||
((splitreq.flags & 0x07) == 0x0)) {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
} else {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
}
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
if (ret)
return ret;
/* blit second region */
if (((splitreq.flags & 0x07) == MDP_ROT_90) ||
((splitreq.flags & 0x07) == 0x0)) {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
} else {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
}
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
return ret;
}
/* Splits a blit into two vertical stripes. Used to work around MDP bugs */
static int blit_split_width(struct mdp_info *mdp, const struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start, unsigned long src_len,
struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
{
int ret;
struct mdp_blit_req splitreq;
int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
splitreq = *req;
/* break dest roi at width*/
d_y_0 = d_y_1 = req->dst_rect.y;
d_h_0 = d_h_1 = req->dst_rect.h;
d_x_0 = req->dst_rect.x;
if (req->dst_rect.w % 32 == 6)
d_w_1 = req->dst_rect.w / 2 - 1;
else if (req->dst_rect.w % 2 == 0)
d_w_1 = req->dst_rect.w / 2;
else if (req->dst_rect.w % 32 == 3)
d_w_1 = (req->dst_rect.w - 3) / 2 - 1;
else
d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
d_w_0 = req->dst_rect.w - d_w_1;
d_x_1 = d_x_0 + d_w_0;
if (req->dst_rect.w == 3) {
d_w_1 = 2;
d_w_0 = 2;
d_x_1 = d_x_0 + 1;
}
/* break src roi at height or width*/
if (splitreq.flags & MDP_ROT_90) {
s_x_0 = s_x_1 = req->src_rect.x;
s_w_0 = s_w_1 = req->src_rect.w;
s_y_0 = req->src_rect.y;
s_h_1 = (req->src_rect.h * d_w_1) / req->dst_rect.w;
s_h_0 = req->src_rect.h - s_h_1;
s_y_1 = s_y_0 + s_h_0;
if (d_w_1 >= 8 * s_h_1) {
s_h_1++;
s_y_1--;
}
} else {
s_y_0 = s_y_1 = req->src_rect.y;
s_h_0 = s_h_1 = req->src_rect.h;
s_x_0 = req->src_rect.x;
s_w_1 = (req->src_rect.w * d_w_1) / req->dst_rect.w;
s_w_0 = req->src_rect.w - s_w_1;
s_x_1 = s_x_0 + s_w_0;
if (d_w_1 >= 8 * s_w_1) {
s_w_1++;
s_x_1--;
}
}
/* blit first region */
if (((splitreq.flags & 0x07) == MDP_ROT_270) ||
((splitreq.flags & 0x07) == 0x0)) {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
} else {
splitreq.src_rect.h = s_h_0;
splitreq.src_rect.y = s_y_0;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_0;
splitreq.src_rect.w = s_w_0;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
}
if (unlikely((splitreq.dst_rect.h != 1) &&
((splitreq.dst_rect.h % 32 == 3) ||
(splitreq.dst_rect.h % 32) == 1)))
ret = blit_split_height(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
else
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
if (ret)
return ret;
/* blit second region */
if (((splitreq.flags & 0x07) == MDP_ROT_270) ||
((splitreq.flags & 0x07) == 0x0)) {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_1;
splitreq.dst_rect.y = d_y_1;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_1;
splitreq.dst_rect.w = d_w_1;
} else {
splitreq.src_rect.h = s_h_1;
splitreq.src_rect.y = s_y_1;
splitreq.dst_rect.h = d_h_0;
splitreq.dst_rect.y = d_y_0;
splitreq.src_rect.x = s_x_1;
splitreq.src_rect.w = s_w_1;
splitreq.dst_rect.x = d_x_0;
splitreq.dst_rect.w = d_w_0;
}
if (unlikely((splitreq.dst_rect.h != 1) &&
((splitreq.dst_rect.h % 32 == 3) ||
(splitreq.dst_rect.h % 32) == 1)))
ret = blit_split_height(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
else
ret = mdp_ppp_blit_and_wait(mdp, &splitreq,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
return ret;
}
int mdp_ppp_validate_blit(struct mdp_info *mdp, struct mdp_blit_req *req)
{
if (req->flags & MDP_ROT_90) {
if (unlikely(((req->dst_rect.h == 1) &&
((req->src_rect.w != 1) ||
(req->dst_rect.w != req->src_rect.h))) ||
((req->dst_rect.w == 1) && ((req->src_rect.h != 1) ||
(req->dst_rect.h != req->src_rect.w))))) {
pr_err("mpd_ppp: error scaling when size is 1!\n");
return -EINVAL;
}
} else {
if (unlikely(((req->dst_rect.w == 1) &&
((req->src_rect.w != 1) ||
(req->dst_rect.h != req->src_rect.h))) ||
((req->dst_rect.h == 1) && ((req->src_rect.h != 1) ||
(req->dst_rect.h != req->src_rect.h))))) {
pr_err("mpd_ppp: error scaling when size is 1!\n");
return -EINVAL;
}
}
/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
if (unlikely(req->src_rect.h == 0 ||
req->src_rect.w == 0)) {
pr_info("mdp_ppp: src img of zero size!\n");
return -EINVAL;
}
if (unlikely(req->dst_rect.h == 0 ||
req->dst_rect.w == 0))
return -EINVAL;
return 0;
}
int mdp_ppp_do_blit(struct mdp_info *mdp, struct mdp_blit_req *req,
struct file *src_file, unsigned long src_start,
unsigned long src_len, struct file *dst_file,
unsigned long dst_start, unsigned long dst_len)
{
int ret;
/* Workarounds for MDP 3.1 hardware bugs */
if (unlikely((mdp_get_bytes_per_pixel(req->dst.format) == 4) &&
(req->dst_rect.w != 1) &&
(((req->dst_rect.w % 8) == 6) ||
((req->dst_rect.w % 32) == 3) ||
((req->dst_rect.w % 32) == 1)))) {
ret = blit_split_width(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
goto end;
} else if (unlikely((req->dst_rect.w != 1) && (req->dst_rect.h != 1) &&
((req->dst_rect.h % 32) == 3 ||
(req->dst_rect.h % 32) == 1))) {
ret = blit_split_height(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
goto end;
}
ret = mdp_ppp_blit_and_wait(mdp, req,
src_file, src_start, src_len,
dst_file, dst_start, dst_len);
end:
return ret;
}

View File

@ -33,11 +33,17 @@
#include <linux/debugfs.h>
#include <linux/dma-mapping.h>
#include <linux/android_pmem.h>
#include "mdp_hw.h"
extern void start_drawing_late_resume(struct early_suspend *h);
static void msmfb_resume_handler(struct early_suspend *h);
static void msmfb_resume(struct work_struct *work);
#ifdef CONFIG_MSM_HDMI
void hdmi_DoBlit(int offset);
int hdmi_usePanelSync(void);
#endif
#define MSMFB_DEBUG 1
#ifdef CONFIG_FB_MSM_LOGO
#define INIT_IMAGE_FILE "/logo.rle"
@ -59,6 +65,11 @@ extern int load_565rle_image(char *filename);
#define BLIT_TIME 0x4
#define SHOW_UPDATES 0x8
#ifdef CONFIG_PANEL_SELF_REFRESH
extern struct panel_icm_info *panel_icm;
extern wait_queue_head_t panel_update_wait_queue;
#endif
#define DLOG(mask, fmt, args...) \
do { \
if ((msmfb_debug_mask | SUSPEND_RESUME) & mask) \
@ -72,6 +83,7 @@ module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
S_IRUGO | S_IWUSR | S_IWGRP);
struct mdp_device *mdp;
static atomic_t mdpclk_on = ATOMIC_INIT(1);
struct msmfb_info {
struct fb_info *fb;
@ -91,9 +103,13 @@ struct msmfb_info {
int ebottom; /* exclusive */
} update_info;
char *black;
#ifdef CONFIG_HTC_ONMODE_CHARGING
struct early_suspend onchg_earlier_suspend;
struct early_suspend onchg_suspend;
#endif
struct early_suspend earlier_suspend;
struct early_suspend early_suspend;
struct wake_lock idle_lock;
spinlock_t update_lock;
struct mutex panel_init_lock;
@ -166,7 +182,7 @@ static int msmfb_release(struct fb_info *info, int user)
/* Called from dma interrupt handler, must not sleep */
static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
{
unsigned long irq_flags;
unsigned long irq_flags=0;
struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
dma_callback);
#if PRINT_FPS
@ -178,6 +194,7 @@ static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
msmfb->frame_done = msmfb->frame_requested;
if (msmfb->sleeping == UPDATING &&
msmfb->frame_done == msmfb->update_frame) {
DLOG(SUSPEND_RESUME, "full update completed\n");
@ -203,7 +220,7 @@ static int msmfb_start_dma(struct msmfb_info *msmfb)
{
uint32_t x, y, w, h;
unsigned addr;
unsigned long irq_flags;
unsigned long irq_flags=0;
uint32_t yoffset;
s64 time_since_request;
struct msm_panel_data *panel = msmfb->panel;
@ -230,11 +247,13 @@ static int msmfb_start_dma(struct msmfb_info *msmfb)
y = msmfb->update_info.top;
w = msmfb->update_info.eright - x;
h = msmfb->update_info.ebottom - y;
#if 0 /* zeusk: */
;;;;;;ASD
#if defined(CONFIG_FRAMEBUFFER_CONSOLE)
x = 0; y = 0; w = msmfb->xres; h = msmfb->yres;
#endif
ASD;;;;;;
#endif
yoffset = msmfb->yoffset;
msmfb->update_info.left = msmfb->xres + 1;
msmfb->update_info.top = msmfb->yres + 1;
@ -287,7 +306,10 @@ static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
{
struct msmfb_info *msmfb = info->par;
struct msm_panel_data *panel = msmfb->panel;
unsigned long irq_flags;
#ifdef CONFIG_PANEL_SELF_REFRESH
struct mdp_lcdc_info *lcdc = panel_to_lcdc(panel);
#endif
unsigned long irq_flags=0;
int sleeping;
int retry = 1;
#if PRINT_FPS
@ -300,16 +322,21 @@ static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
left, top, eright, ebottom, yoffset, pan_display);
#if !defined(CONFIG_MACH_HTCLEO)
// For some reason we need to remove it here, state is 1, we have to look later to this problem
if (msmfb->sleeping != AWAKE)
DLOG(SUSPEND_RESUME, "pan_update in state(%d)\n", msmfb->sleeping);
#ifdef CONFIG_PANEL_SELF_REFRESH
if (lcdc->mdp->mdp_dev.overrides & MSM_MDP_RGB_PANEL_SELE_REFRESH) {
spin_lock_irqsave(&panel_icm->lock, irq_flags);
panel_icm->panel_update = 1;
spin_unlock_irqrestore(&panel_icm->lock, irq_flags);
wake_up(&panel_update_wait_queue);
}
#endif
#if (defined(CONFIG_USB_FUNCTION_PROJECTOR) || defined(CONFIG_USB_ANDROID_PROJECTOR))
/* Jay, 8/1/09' */
msmfb_set_var(msmfb->fb->screen_base, yoffset);
#endif
if (msmfb->sleeping != AWAKE)
DLOG(SUSPEND_RESUME, "pan_update in state(%d)\n", msmfb->sleeping);
restart:
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
@ -401,19 +428,35 @@ restart:
msmfb->yoffset);
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
/* if the panel is all the way on wait for vsync, otherwise sleep
* for 16 ms (long enough for the dma to panel) and then begin dma */
msmfb->vsync_request_time = ktime_get();
if (panel->request_vsync && (sleeping == AWAKE)) {
wake_lock_timeout(&msmfb->idle_lock, HZ/4);
panel->request_vsync(panel, &msmfb->vsync_callback);
} else {
if (!hrtimer_active(&msmfb->fake_vsync)) {
hrtimer_start(&msmfb->fake_vsync,
ktime_set(0, NSEC_PER_SEC/60),
HRTIMER_MODE_REL);
}
}
#ifdef CONFIG_MSM_HDMI
if (!hdmi_usePanelSync())
{
msmfb->vsync_request_time = ktime_get();
msmfb_start_dma(msmfb);
}
else
{
#endif
/* if the panel is all the way on wait for vsync, otherwise sleep
* for 16 ms (long enough for the dma to panel) and then begin dma */
msmfb->vsync_request_time = ktime_get();
if (panel->request_vsync && (sleeping == AWAKE)) {
wake_lock_timeout(&msmfb->idle_lock, HZ/4);
panel->request_vsync(panel, &msmfb->vsync_callback);
} else {
if (!hrtimer_active(&msmfb->fake_vsync)) {
hrtimer_start(&msmfb->fake_vsync,
ktime_set(0, NSEC_PER_SEC/60),
HRTIMER_MODE_REL);
}
}
#ifdef CONFIG_MSM_HDMI
}
/* We did the DMA, now blit the data to the other display */
hdmi_DoBlit(msmfb->xres * msmfb->yoffset * BYTES_PER_PIXEL(msmfb));
#endif
return;
}
static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
@ -427,7 +470,7 @@ static void power_on_panel(struct work_struct *work)
struct msmfb_info *msmfb =
container_of(work, struct msmfb_info, resume_work);
struct msm_panel_data *panel = msmfb->panel;
unsigned long irq_flags;
unsigned long irq_flags=0;
mutex_lock(&msmfb->panel_init_lock);
DLOG(SUSPEND_RESUME, "turning on panel\n");
if (msmfb->sleeping == UPDATING) {
@ -447,34 +490,33 @@ error:
mutex_unlock(&msmfb->panel_init_lock);
}
static BLOCKING_NOTIFIER_HEAD(display_chain_head);
int register_display_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&display_chain_head, nb);
}
static int display_notifier_callback(struct notifier_block *nfb,
unsigned long action,
void *ignored)
{
struct msmfb_info *msm_fb = (struct msmfb_info *)ignored;
static BLOCKING_NOTIFIER_HEAD(display_chain_head);
int register_display_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&display_chain_head, nb);
}
static int display_notifier_callback(struct notifier_block *nfb,
unsigned long action,
void *ignored)
{
//struct msmfb_info *msm_fb = (struct msmfb_info *)ignored;
switch (action) {
case NOTIFY_MSM_FB:
printk(KERN_DEBUG "NOTIFY_MSM_FB\n");
msmfb_resume(&msm_fb->early_suspend);
break;
printk(KERN_DEBUG "NOTIFY_MSM_FB\n");
//msmfb_resume(&msm_fb->early_suspend);
break;
case NOTIFY_POWER:
/* nothing to do */
break;
/* nothing to do */
break;
default:
printk(KERN_ERR "%s: unknown action in 0x%lx\n",
__func__, action);
return NOTIFY_BAD;
printk(KERN_ERR "%s: unknown action in 0x%lx\n",
__func__, action);
return NOTIFY_BAD;
}
return NOTIFY_OK;
}
}
/* -------------------------------------------------------------------------- */
#ifdef CONFIG_HAS_EARLYSUSPEND
/* turn off the panel */
static void msmfb_earlier_suspend(struct early_suspend *h)
@ -482,7 +524,7 @@ static void msmfb_earlier_suspend(struct early_suspend *h)
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
earlier_suspend);
struct msm_panel_data *panel = msmfb->panel;
unsigned long irq_flags;
unsigned long irq_flags=0;
mutex_lock(&msmfb->panel_init_lock);
msmfb->sleeping = SLEEPING;
@ -513,6 +555,8 @@ static void msmfb_suspend(struct early_suspend *h)
overlay_event.event_wait,
(overlay_event.waked_up == ~USE_OVERLAY),
10*HZ);
/*wait until USE_OVERLAY flag is off and set mdpclk_on as off*/
atomic_set(&mdpclk_on, 0);
pr_info("wait event : %X\n", overlay_event.waked_up);
#endif
panel->suspend(panel);
@ -523,17 +567,81 @@ static void msmfb_suspend(struct early_suspend *h)
static void msmfb_resume_handler(struct early_suspend *h)
{
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
early_suspend);
early_suspend);
#ifdef CONFIG_HTC_ONMODE_CHARGING
if (msmfb->fb_resumed == 1) {
DLOG(SUSPEND_RESUME, "fb is resumed by onchg. skip resume\n");
return;
}
#endif
queue_work(msmfb->resume_workqueue, &msmfb->msmfb_resume_work);
wait_event_interruptible_timeout(msmfb->frame_wq, msmfb->fb_resumed==1,HZ/2);
}
#ifdef CONFIG_HTC_ONMODE_CHARGING
static void msmfb_onchg_earlier_suspend(struct early_suspend *h)
{
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
onchg_earlier_suspend);
struct msm_panel_data *panel = msmfb->panel;
unsigned long irq_flags=0;
mutex_lock(&msmfb->panel_init_lock);
msmfb->sleeping = SLEEPING;
wake_up(&msmfb->frame_wq);
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
#ifndef CONFIG_MSM_MDP40
mdp->dma(mdp, virt_to_phys(msmfb->black), 0,
msmfb->fb->var.xres, msmfb->fb->var.yres, 0, 0,
NULL, panel->interface_type);
mdp->dma_wait(mdp, panel->interface_type);
#endif
wait_event_timeout(msmfb->frame_wq,
msmfb->frame_requested == msmfb->frame_done, HZ/10);
/* turn off the panel */
panel->blank(panel);
}
static void msmfb_onchg_suspend(struct early_suspend *h)
{
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
onchg_suspend);
struct msm_panel_data *panel = msmfb->panel;
/* suspend the panel */
#ifdef CONFIG_FB_MSM_OVERLAY
/*check whether overlay done*/
wait_event_interruptible_timeout(
overlay_event.event_wait,
(overlay_event.waked_up == ~USE_OVERLAY),
10*HZ);
/*wait until USE_OVERLAY flag is off and set mdpclk_on as off*/
atomic_set(&mdpclk_on, 0);
pr_info("wait event : %X\n", overlay_event.waked_up);
#endif
panel->suspend(panel);
msmfb->fb_resumed = 0;
mutex_unlock(&msmfb->panel_init_lock);
}
static void msmfb_onchg_resume_handler(struct early_suspend *h)
{
struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
onchg_suspend);
queue_work(msmfb->resume_workqueue, &msmfb->msmfb_resume_work);
wait_event_interruptible_timeout(msmfb->frame_wq, msmfb->fb_resumed == 1, HZ/2);
}
#endif
static void msmfb_resume(struct work_struct *work)
{
struct msmfb_info *msmfb =
container_of(work, struct msmfb_info, msmfb_resume_work);
struct msm_panel_data *panel = msmfb->panel;
unsigned long irq_flags;
unsigned long irq_flags=0;
if (panel->resume(panel)) {
printk(KERN_INFO "msmfb: panel resume failed, not resuming "
@ -545,15 +653,16 @@ static void msmfb_resume(struct work_struct *work)
msmfb->sleeping = WAKING;
DLOG(SUSPEND_RESUME, "ready, waiting for full update\n");
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
start_drawing_late_resume(NULL);
msmfb->fb_resumed = 1;
wake_up(&msmfb->frame_wq);
atomic_set(&mdpclk_on, 1);
}
#endif
static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
u32 size;
uint32_t size;
if ((var->xres != info->var.xres) ||
(var->yres != info->var.yres) ||
@ -625,28 +734,22 @@ int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
cfb_fillrect(p, rect);
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
rect->dy + rect->height);
#endif
}
static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
{
cfb_copyarea(p, area);
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
msmfb_update(p, area->dx, area->dy, area->dx + area->width,
area->dy + area->height);
#endif
}
static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
{
cfb_imageblit(p, image);
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
msmfb_update(p, image->dx, image->dy, image->dx + image->width,
image->dy + image->height);
#endif
}
@ -705,6 +808,7 @@ static int msmfb_overlay_set(struct fb_info *info, void __user *p)
if (copy_from_user(&req, p, sizeof(req)))
return -EFAULT;
printk(KERN_INFO "%s(%d) dst rect info w=%d h=%d x=%d y=%d rotator=%d\n", __func__, __LINE__, req.dst_rect.w, req.dst_rect.h, req.dst_rect.x, req.dst_rect.y, req.user_data[0]);
ret = mdp->overlay_set(mdp, info, &req);
if (ret) {
printk(KERN_ERR "%s:ioctl failed \n",
@ -764,7 +868,7 @@ DEFINE_MUTEX(mdp_ppp_lock);
static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int ret;
int ret = 0;
#if PRINT_BLIT_TIME
ktime_t t1, t2;
#endif
@ -788,41 +892,41 @@ static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
break;
#ifdef CONFIG_FB_MSM_OVERLAY
case MSMFB_OVERLAY_GET:
printk("CONFIG_FB_MSM_OVERLAY\n");
//down(&mdp_ppp_lock);
ret = msmfb_overlay_get(p, argp);
//up(&mdp_ppp_lock);
break;
case MSMFB_OVERLAY_SET:
printk("MSMFB_OVERLAY_SET\n");
//down(&mdp_ppp_lock);
ret = msmfb_overlay_set(p, argp);
mutex_lock(&overlay_event_lock);
overlay_event.waked_up = USE_OVERLAY;
mutex_unlock(&overlay_event_lock);
//up(&mdp_ppp_lock);
if(!atomic_read(&mdpclk_on)) {
printk(KERN_ERR "MSMFB_OVERLAY_SET during suspend\n");
ret = -EINVAL;
} else {
mutex_lock(&overlay_event_lock);
overlay_event.waked_up = USE_OVERLAY;
mutex_unlock(&overlay_event_lock);
ret = msmfb_overlay_set(p, argp);
}
printk(KERN_INFO "MSMFB_OVERLAY_SET ret=%d\n", ret);
break;
case MSMFB_OVERLAY_UNSET:
printk("MSMFB_OVERLAY_UNSET\n");
//down(&mdp_ppp_lock);
ret = msmfb_overlay_unset(p, argp);
mutex_lock(&overlay_event_lock);
overlay_event.waked_up = ~USE_OVERLAY;
wake_up(&overlay_event.event_wait);
mutex_unlock(&overlay_event_lock);
//up(&mdp_ppp_lock);
printk(KERN_INFO "MSMFB_OVERLAY_UNSET ret=%d\n", ret);
break;
case MSMFB_OVERLAY_PLAY:
//down(&mdp_ppp_lock);
ret = msmfb_overlay_play(p, argp);
//up(&mdp_ppp_lock);
if(!atomic_read(&mdpclk_on)) {
printk(KERN_ERR "MSMFB_OVERLAY_PLAY during suspend\n");
ret = -EINVAL;
} else
ret = msmfb_overlay_play(p, argp);
break;
#endif
default:
printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
return -EINVAL;
}
return 0;
return ret;
}
static struct fb_ops msmfb_ops = {
@ -856,7 +960,7 @@ static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
static char buffer[4096];
int n = 0;
struct msmfb_info *msmfb = (struct msmfb_info *)file->private_data;
unsigned long irq_flags;
unsigned long irq_flags=0;
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
n = scnprintf(buffer, debug_bufmax, "yoffset %d\n", msmfb->yoffset);
@ -880,7 +984,7 @@ static struct file_operations debug_fops = {
};
#endif
#define BITS_PER_PIXEL 16
#define BITS_PER_PIXEL_DEF 32
static void setup_fb_info(struct msmfb_info *msmfb)
{
@ -904,8 +1008,9 @@ static void setup_fb_info(struct msmfb_info *msmfb)
fb_info->var.height = msmfb->panel->fb_data->height;
fb_info->var.xres_virtual = msmfb->xres;
fb_info->var.yres_virtual = msmfb->yres * 2;
fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
fb_info->var.bits_per_pixel = BITS_PER_PIXEL_DEF;
fb_info->var.accel_flags = 0;
fb_info->var.reserved[4] = 60;
fb_info->var.yoffset = 0;
@ -938,6 +1043,7 @@ static void setup_fb_info(struct msmfb_info *msmfb)
fb_info->var.blue.msb_right = 0;
mdp->set_output_format(mdp, fb_info->var.bits_per_pixel);
mdp->set_panel_size(mdp, msmfb->xres, msmfb->yres);
r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
fb_info->pseudo_palette = PP;
@ -1027,7 +1133,7 @@ static int msmfb_probe(struct platform_device *pdev)
spin_lock_init(&msmfb->update_lock);
mutex_init(&msmfb->panel_init_lock);
init_waitqueue_head(&msmfb->frame_wq);
msmfb->resume_workqueue = create_rt_workqueue("panel_on");
msmfb->resume_workqueue = create_workqueue("panel_on");
if (msmfb->resume_workqueue == NULL) {
printk(KERN_ERR "failed to create panel_on workqueue\n");
ret = -ENOMEM;
@ -1049,6 +1155,16 @@ static int msmfb_probe(struct platform_device *pdev)
msmfb->earlier_suspend.suspend = msmfb_earlier_suspend;
msmfb->earlier_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
register_early_suspend(&msmfb->earlier_suspend);
#ifdef CONFIG_HTC_ONMODE_CHARGING
msmfb->onchg_suspend.suspend = msmfb_onchg_suspend;
msmfb->onchg_suspend.resume = msmfb_onchg_resume_handler;
msmfb->onchg_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
register_onchg_suspend(&msmfb->onchg_suspend);
msmfb->onchg_earlier_suspend.suspend = msmfb_onchg_earlier_suspend;
msmfb->onchg_earlier_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
register_onchg_suspend(&msmfb->onchg_earlier_suspend);
#endif
#endif
#if MSMFB_DEBUG
@ -1082,10 +1198,10 @@ static int msmfb_probe(struct platform_device *pdev)
#ifdef CONFIG_FB_MSM_LOGO
if (!load_565rle_image(INIT_IMAGE_FILE)) {
/* Flip buffer */
msmfb->update_info.left = 0;
msmfb->update_info.left = 0;
msmfb->update_info.top = 0;
msmfb->update_info.eright = msmfb->xres;
msmfb->update_info.ebottom = msmfb->yres;
msmfb->update_info.ebottom = msmfb->yres;
msmfb_pan_update(msmfb->fb, 0, 0, msmfb->xres,
msmfb->yres, 0, 1);
}

View File

@ -3,13 +3,31 @@
#include <linux/types.h>
#include <linux/i2c.h>
struct dentry;
/* Definitions of frame buffers */
#define FB_MAX 32 /* sufficient for now */
struct fbcon_decor_iowrapper
{
unsigned short vc; /* Virtual console */
unsigned char origin; /* Point of origin of the request */
void *data;
};
#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
struct fbcon_decor_iowrapper32
{
unsigned short vc; /* Virtual console */
unsigned char origin; /* Point of origin of the request */
compat_uptr_t data;
};
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
/* ioctls
0x46 is 'F' */
#define FBIOGET_VSCREENINFO 0x4600
@ -37,7 +55,24 @@ struct dentry;
#define FBIOGET_HWCINFO 0x4616
#define FBIOPUT_MODEINFO 0x4617
#define FBIOGET_DISPINFO 0x4618
#define FBIOCONDECOR_SETCFG _IOWR('F', 0x19, struct fbcon_decor_iowrapper)
#define FBIOCONDECOR_GETCFG _IOR('F', 0x1A, struct fbcon_decor_iowrapper)
#define FBIOCONDECOR_SETSTATE _IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
#define FBIOCONDECOR_GETSTATE _IOR('F', 0x1C, struct fbcon_decor_iowrapper)
#define FBIOCONDECOR_SETPIC _IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
#define FBIOCONDECOR_SETCFG32 _IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
#define FBIOCONDECOR_GETCFG32 _IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
#define FBIOCONDECOR_SETSTATE32 _IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
#define FBIOCONDECOR_GETSTATE32 _IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
#define FBIOCONDECOR_SETPIC32 _IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#define FBCON_DECOR_THEME_LEN 128 /* Maximum lenght of a theme name */
#define FBCON_DECOR_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */
#define FBCON_DECOR_IO_ORIG_USER 1 /* User ioctl origin */
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
@ -282,6 +317,28 @@ struct fb_cmap {
__u16 *transp; /* transparency, can be NULL */
};
#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
struct fb_cmap32 {
__u32 start;
__u32 len; /* Number of entries */
compat_uptr_t red; /* Red values */
compat_uptr_t green;
compat_uptr_t blue;
compat_uptr_t transp; /* transparency, can be NULL */
};
#define fb_cmap_from_compat(to, from) \
(to).start = (from).start; \
(to).len = (from).len; \
(to).red = compat_ptr((from).red); \
(to).green = compat_ptr((from).green); \
(to).blue = compat_ptr((from).blue); \
(to).transp = compat_ptr((from).transp)
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
struct fb_con2fbmap {
__u32 console;
__u32 framebuffer;
@ -363,6 +420,34 @@ struct fb_image {
struct fb_cmap cmap; /* color map info */
};
#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
struct fb_image32 {
__u32 dx; /* Where to place image */
__u32 dy;
__u32 width; /* Size of image */
__u32 height;
__u32 fg_color; /* Only used when a mono bitmap */
__u32 bg_color;
__u8 depth; /* Depth of the image */
const compat_uptr_t data; /* Pointer to image data */
struct fb_cmap32 cmap; /* color map info */
};
#define fb_image_from_compat(to, from) \
(to).dx = (from).dx; \
(to).dy = (from).dy; \
(to).width = (from).width; \
(to).height = (from).height; \
(to).fg_color = (from).fg_color; \
(to).bg_color = (from).bg_color; \
(to).depth = (from).depth; \
(to).data = compat_ptr((from).data); \
fb_cmap_from_compat((to).cmap, (from).cmap)
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
/*
* hardware cursor control
*/
@ -403,6 +488,7 @@ struct fb_cursor {
#include <linux/notifier.h>
#include <linux/list.h>
#include <linux/backlight.h>
#include <linux/slab.h>
#include <asm/io.h>
struct vm_area_struct;
@ -543,6 +629,8 @@ struct fb_cursor_user {
#define FB_EVENT_GET_REQ 0x0D
/* Unbind from the console if possible */
#define FB_EVENT_FB_UNBIND 0x0E
/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */
#define FB_EVENT_REMAP_ALL_CONSOLE 0x0F
struct fb_event {
struct fb_info *info;
@ -606,6 +694,12 @@ struct fb_deferred_io {
* LOCKING NOTE: those functions must _ALL_ be called with the console
* semaphore held, this is the only suitable locking mechanism we have
* in 2.6. Some may be called at interrupt time at this point though.
*
* The exception to this is the debug related hooks. Putting the fb
* into a debug state (e.g. flipping to the kernel console) and restoring
* it must be done in a lock-free manner, so low level drivers should
* keep track of the initial console (if applicable) and may need to
* perform direct, unlocked hardware writes in these hooks.
*/
struct fb_ops {
@ -675,6 +769,10 @@ struct fb_ops {
/* teardown any resources to do with this framebuffer */
void (*fb_destroy)(struct fb_info *info);
/* called at KDB enter and leave time to prepare the console */
int (*fb_debug_enter)(struct fb_info *info);
int (*fb_debug_leave)(struct fb_info *info);
};
#ifdef CONFIG_FB_TILEBLITTING
@ -763,6 +861,7 @@ struct fb_tile_ops {
* takes over; acceleration engine should be in a quiescent state */
/* hints */
#define FBINFO_VIRTFB 0x0004 /* FB is System RAM, not device. */
#define FBINFO_PARTIAL_PAN_OK 0x0040 /* otw use pan only for double-buffering */
#define FBINFO_READS_FAST 0x0080 /* soft-copy faster than rendering */
@ -784,8 +883,6 @@ struct fb_tile_ops {
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
#define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware
inited framebuffer */
/* A driver may set this flag to indicate that it does want a set_par to be
* called every time when fbcon_switch is executed. The advantage is that with
@ -799,6 +896,8 @@ struct fb_tile_ops {
*/
#define FBINFO_MISC_ALWAYS_SETPAR 0x40000
/* where the fb is a firmware driver, and can be replaced with a proper one */
#define FBINFO_MISC_FIRMWARE 0x80000
/*
* Host and GPU endianness differ.
*/
@ -810,6 +909,10 @@ struct fb_tile_ops {
*/
#define FBINFO_BE_MATH 0x100000
/* report to the VT layer that this fb driver can accept forced console
output like oopses */
#define FBINFO_CAN_FORCE_OUTPUT 0x200000
struct fb_info {
int node;
int flags;
@ -854,15 +957,32 @@ struct fb_info {
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
struct fb_image bgdecor;
/* From here on everything is device dependent */
void *par;
/* we need the PCI or similiar aperture base/size not
smem_start/size as smem_start may just be an object
allocated inside the aperture so may not actually overlap */
resource_size_t aperture_base;
resource_size_t aperture_size;
struct apertures_struct {
unsigned int count;
struct aperture {
resource_size_t base;
resource_size_t size;
} ranges[0];
} *apertures;
};
static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
struct apertures_struct *a = kzalloc(sizeof(struct apertures_struct)
+ max_num * sizeof(struct aperture), GFP_KERNEL);
if (!a)
return NULL;
a->count = max_num;
return a;
}
#ifdef MODULE
#define FBINFO_DEFAULT FBINFO_MODULE
#else
@ -898,6 +1018,8 @@ struct fb_info {
#define fb_writel sbus_writel
#define fb_writeq sbus_writeq
#define fb_memset sbus_memset_io
#define fb_memcpy_fromfb sbus_memcpy_fromio
#define fb_memcpy_tofb sbus_memcpy_toio
#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || defined(__avr32__) || defined(__bfin__)
@ -910,6 +1032,8 @@ struct fb_info {
#define fb_writel __raw_writel
#define fb_writeq __raw_writeq
#define fb_memset memset_io
#define fb_memcpy_fromfb memcpy_fromio
#define fb_memcpy_tofb memcpy_toio
#else
@ -922,6 +1046,8 @@ struct fb_info {
#define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b))
#define fb_writeq(b,addr) (*(volatile u64 *) (addr) = (b))
#define fb_memset memset
#define fb_memcpy_fromfb memcpy
#define fb_memcpy_tofb memcpy
#endif
@ -955,6 +1081,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
/* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_framebuffer(struct fb_info *fb_info);
extern void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary);
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
extern int fb_show_logo(struct fb_info *fb_info, int rotate);
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
@ -1052,6 +1180,8 @@ extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
extern const unsigned char *fb_firmware_edid(struct device *device);
extern void fb_edid_to_monspecs(unsigned char *edid,
struct fb_monspecs *specs);
extern void fb_edid_add_monspecs(unsigned char *edid,
struct fb_monspecs *specs);
extern void fb_destroy_modedb(struct fb_videomode *modedb);
extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
@ -1082,6 +1212,7 @@ extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs
/* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
extern int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags);
extern void fb_dealloc_cmap(struct fb_cmap *cmap);
extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to);
extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to);

View File

@ -0,0 +1,209 @@
/* include/linux/msm_audio.h
*
* Copyright (C) 2008 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
#ifndef __LINUX_MSM_AUDIO_H
#define __LINUX_MSM_AUDIO_H
#include <linux/types.h>
#include <linux/ioctl.h>
#include <asm/sizes.h>
/* PCM Audio */
#define AUDIO_IOCTL_MAGIC 'a'
#define AUDIO_ENABLE_AUDPRE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned)
#define AUDIO_SET_AGC _IOW(AUDIO_IOCTL_MAGIC, 12, unsigned)
#define AUDIO_SET_NS _IOW(AUDIO_IOCTL_MAGIC, 13, unsigned)
#define AUDIO_SET_TX_IIR _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned)
#define AUDIO_PLAY_DTMF _IOW(AUDIO_IOCTL_MAGIC, 19, unsigned)
#define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned)
#define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned)
#define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned)
#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned)
#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned)
#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned)
#define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned)
#define AUDIO_SET_ADRC _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned)
#define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned)
#define AUDIO_SET_RX_IIR _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned)
#define AUDIO_SET_VOLUME _IOW(AUDIO_IOCTL_MAGIC, 10, unsigned)
#define AUDIO_PAUSE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned)
#define AUDIO_GET_EVENT _IOR(AUDIO_IOCTL_MAGIC, 13, unsigned)
#define AUDIO_ABORT_GET_EVENT _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned)
#define AUDIO_REGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 15, unsigned)
#define AUDIO_DEREGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 16, unsigned)
#define AUDIO_WAIT_ADSP_DONE _IOR(AUDIO_IOCTL_MAGIC, 16, unsigned)
#define AUDIO_ADSP_PAUSE _IOR(AUDIO_IOCTL_MAGIC, 17, unsigned)
#define AUDIO_ASYNC_WRITE _IOW(AUDIO_IOCTL_MAGIC, 17, unsigned)
#define AUDIO_ADSP_RESUME _IOR(AUDIO_IOCTL_MAGIC, 18, unsigned)
#define AUDIO_ASYNC_READ _IOW(AUDIO_IOCTL_MAGIC, 18, unsigned)
#define AUDIO_SET_INCALL _IOW(AUDIO_IOCTL_MAGIC, 19, \
struct msm_voicerec_mode)
#define AUDIO_GET_NUM_SND_DEVICE _IOR(AUDIO_IOCTL_MAGIC, 20, unsigned)
#define AUDIO_GET_AMRNB_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 21, unsigned)
#define AUDIO_GET_SND_DEVICES _IOWR(AUDIO_IOCTL_MAGIC, 21, \
struct msm_snd_device_list)
#define AUDIO_SET_AMRNB_ENC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 22, unsigned)
#define AUDIO_ENABLE_SND_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 22, unsigned)
#define AUDIO_DISABLE_SND_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 23, unsigned)
#define AUDIO_ROUTE_STREAM _IOW(AUDIO_IOCTL_MAGIC, 24, \
struct msm_audio_route_config)
#define AUDIO_GET_PCM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 30, unsigned)
#define AUDIO_SET_PCM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 31, unsigned)
#define AUDIO_SWITCH_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 32, unsigned)
#define AUDIO_SET_MUTE _IOW(AUDIO_IOCTL_MAGIC, 33, unsigned)
#define AUDIO_UPDATE_ACDB _IOW(AUDIO_IOCTL_MAGIC, 34, unsigned)
#define AUDIO_START_VOICE _IOW(AUDIO_IOCTL_MAGIC, 35, unsigned)
#define AUDIO_STOP_VOICE _IOW(AUDIO_IOCTL_MAGIC, 36, unsigned)
#define AUDIO_START_FM _IOW(AUDIO_IOCTL_MAGIC, 37, unsigned)
#define AUDIO_STOP_FM _IOW(AUDIO_IOCTL_MAGIC, 38, unsigned)
#define AUDIO_REINIT_ACDB _IOW(AUDIO_IOCTL_MAGIC, 39, unsigned)
#define AUDIO_ENABLE_AUXPGA_LOOPBACK _IOW(AUDIO_IOCTL_MAGIC, 40, unsigned)
#define AUDIO_OUTPORT_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 40, \
unsigned short)
#define AUDIO_SET_AUXPGA_GAIN _IOW(AUDIO_IOCTL_MAGIC, 41, unsigned)
#define AUDIO_SET_ERR_THRESHOLD_VALUE _IOW(AUDIO_IOCTL_MAGIC, 41, \
unsigned short)
#define AUDIO_SET_RX_MUTE _IOW(AUDIO_IOCTL_MAGIC, 42, unsigned)
#define AUDIO_GET_BITSTREAM_ERROR_INFO _IOR(AUDIO_IOCTL_MAGIC, 42, \
struct msm_audio_bitstream_error_info)
/* Qualcomm extensions */
#define AUDIO_SET_STREAM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 80, \
struct msm_audio_stream_config)
#define AUDIO_GET_STREAM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 81, \
struct msm_audio_stream_config)
#define AUDIO_GET_SESSION_ID _IOR(AUDIO_IOCTL_MAGIC, 82, \
unsigned short)
#define AUDIO_GET_STREAM_INFO _IOR(AUDIO_IOCTL_MAGIC, 83, \
struct msm_audio_bitstream_info)
#define AUDIO_SET_PAN _IOW(AUDIO_IOCTL_MAGIC, 84, unsigned)
#define AUDIO_SET_QCONCERT_PLUS _IOW(AUDIO_IOCTL_MAGIC, 85, unsigned)
#define AUDIO_SET_MBADRC _IOW(AUDIO_IOCTL_MAGIC, 86, unsigned)
#define AUDIO_SET_VOLUME_PATH _IOW(AUDIO_IOCTL_MAGIC, 87, \
struct msm_vol_info)
#define AUDIO_SET_MAX_VOL_ALL _IOW(AUDIO_IOCTL_MAGIC, 88, unsigned)
#define AUDIO_GET_BUF_CFG _IOW(AUDIO_IOCTL_MAGIC, 93, \
struct msm_audio_buf_cfg)
#define AUDIO_SET_BUF_CFG _IOW(AUDIO_IOCTL_MAGIC, 94, \
struct msm_audio_buf_cfg)
#define AUDIO_SET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 95, \
struct msm_acdb_cmd_device)
#define AUDIO_GET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 96, \
struct msm_acdb_cmd_device)
#define AUDIO_MAX_COMMON_IOCTL_NUM 100
struct msm_audio_config {
uint32_t buffer_size;
uint32_t buffer_count;
uint32_t channel_count;
uint32_t sample_rate;
uint32_t type;
uint32_t unused[3];
};
struct msm_audio_stats {
uint32_t byte_count;
uint32_t sample_count;
uint32_t unused[2];
};
struct msm_mute_info {
uint32_t mute;
uint32_t path;
};
#define AAC_OBJECT_ER_LC 17
#define AAC_OBJECT_ER_LTP 19
#define AAC_OBJECT_ER_SCALABLE 20
#define AAC_OBJECT_BSAC 22
#define AAC_OBJECT_ER_LD 23
struct aac_format {
uint16_t sample_rate;
uint16_t channel_config;
uint16_t block_formats;
uint16_t audio_object_type;
uint16_t ep_config;
uint16_t aac_section_data_resilience_flag;
uint16_t aac_scalefactor_data_resilience_flag;
uint16_t aac_spectral_data_resilience_flag;
uint16_t sbr_on_flag;
uint16_t sbr_ps_on_flag;
uint32_t bit_rate;
};
struct msm_audio_stream_config {
uint32_t buffer_size;
uint32_t buffer_count;
};
/* Audio routing */
#define SND_IOCTL_MAGIC 's'
#define SND_MUTE_UNMUTED 0
#define SND_MUTE_MUTED 1
struct msm_voicerec_mode {
uint32_t rec_mode;
};
struct msm_snd_device_config {
uint32_t device;
uint32_t ear_mute;
uint32_t mic_mute;
};
#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *)
#define SND_METHOD_VOICE 0
struct msm_snd_volume_config {
uint32_t device;
uint32_t method;
uint32_t volume;
};
#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *)
/* Returns the number of SND endpoints supported. */
#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
struct msm_snd_endpoint {
int id; /* input and output */
char name[64]; /* output only */
};
/* Takes an index between 0 and one less than the number returned by
* SND_GET_NUM_ENDPOINTS, and returns the SND index and name of a
* SND endpoint. On input, the .id field contains the number of the
* endpoint, and on exit it contains the SND index, while .name contains
* the description of the endpoint.
*/
#define SND_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_snd_endpoint *)
struct msm_audio_pcm_config {
uint32_t pcm_feedback; /* 0 - disable > 0 - enable */
uint32_t buffer_count; /* Number of buffers to allocate */
uint32_t buffer_size; /* Size of buffer for capturing of
PCM samples */
};
#endif

View File

@ -0,0 +1,91 @@
/* arch/arm/mach-msm/include/mach/msm_audio_aac.h
*
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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, you can find it at http://www.fsf.org.
*
*/
#ifndef __MSM_AUDIO_AAC_H
#define __MSM_AUDIO_AAC_H
#include <linux/msm_audio_1550.h>
#define AUDIO_SET_AAC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+0), unsigned)
#define AUDIO_GET_AAC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+1), unsigned)
#define AUDIO_SET_AAC_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_aac_enc_config)
#define AUDIO_GET_AAC_ENC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+4), struct msm_audio_aac_enc_config)
#define AUDIO_AAC_FORMAT_ADTS -1
#define AUDIO_AAC_FORMAT_RAW 0x0000
#define AUDIO_AAC_FORMAT_PSUEDO_RAW 0x0001
#define AUDIO_AAC_FORMAT_LOAS 0x0002
#define AUDIO_AAC_FORMAT_ADIF 0x0003
#define AUDIO_AAC_OBJECT_LC 0x0002
#define AUDIO_AAC_OBJECT_LTP 0x0004
#define AUDIO_AAC_OBJECT_ERLC 0x0011
#define AUDIO_AAC_OBJECT_BSAC 0x0016
#define AUDIO_AAC_SEC_DATA_RES_ON 0x0001
#define AUDIO_AAC_SEC_DATA_RES_OFF 0x0000
#define AUDIO_AAC_SCA_DATA_RES_ON 0x0001
#define AUDIO_AAC_SCA_DATA_RES_OFF 0x0000
#define AUDIO_AAC_SPEC_DATA_RES_ON 0x0001
#define AUDIO_AAC_SPEC_DATA_RES_OFF 0x0000
#define AUDIO_AAC_SBR_ON_FLAG_ON 0x0001
#define AUDIO_AAC_SBR_ON_FLAG_OFF 0x0000
#define AUDIO_AAC_SBR_PS_ON_FLAG_ON 0x0001
#define AUDIO_AAC_SBR_PS_ON_FLAG_OFF 0x0000
/* Primary channel on both left and right channels */
#define AUDIO_AAC_DUAL_MONO_PL_PR 0
/* Secondary channel on both left and right channels */
#define AUDIO_AAC_DUAL_MONO_SL_SR 1
/* Primary channel on right channel and 2nd on left channel */
#define AUDIO_AAC_DUAL_MONO_SL_PR 2
/* 2nd channel on right channel and primary on left channel */
#define AUDIO_AAC_DUAL_MONO_PL_SR 3
struct msm_audio_aac_config {
signed short format;
unsigned short audio_object;
unsigned short ep_config; /* 0 ~ 3 useful only obj = ERLC */
unsigned short aac_section_data_resilience_flag;
unsigned short aac_scalefactor_data_resilience_flag;
unsigned short aac_spectral_data_resilience_flag;
unsigned short sbr_on_flag;
unsigned short sbr_ps_on_flag;
unsigned short dual_mono_mode;
unsigned short channel_configuration;
};
struct msm_audio_aac_enc_config {
uint32_t channels;
uint32_t sample_rate;
uint32_t bit_rate;
uint32_t stream_format;
};
#endif /* __MSM_AUDIO_AAC_H */

View File

@ -19,36 +19,21 @@
#define MSMFB_IOCTL_MAGIC 'm'
#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int)
#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int)
#ifdef CONFIG_MSM_MDP40
#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \
struct mdp_overlay)
#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \
struct msmfb_overlay_data)
#define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \
struct mdp_overlay)
#endif
enum {
MDP_RGB_565, // RGB 565 planer
MDP_XRGB_8888, // RGB 888 padded
MDP_Y_CBCR_H2V2, // Y and CbCr, pseudo planer w/ Cb is in MSB
MDP_ARGB_8888, // ARGB 888
MDP_RGB_888, // RGB 888 planer
MDP_Y_CRCB_H2V2, // Y and CrCb, pseudo planer w/ Cr is in MSB
MDP_YCRYCB_H2V1, // YCrYCb interleave
MDP_Y_CRCB_H2V1, // Y and CrCb, pseduo planer w/ Cr is in MSB
MDP_Y_CBCR_H2V1, // Y and CrCb, pseduo planer w/ Cr is in MSB
MDP_RGBA_8888, // ARGB 888
MDP_BGRA_8888, // ARGB 888
MDP_RGBX_8888, // RGBX 888
MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */
MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */
MDP_IMGTYPE_LIMIT, // Non valid image type after this enum
MDP_IMGTYPE2_START = 0x10000,
MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */
MDP_FB_FORMAT, /* framebuffer format */
MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
MDP_RGB_565, /* RGB 565 planar */
MDP_XRGB_8888, /* RGB 888 padded */
MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planar w/ Cb is in MSB */
MDP_ARGB_8888, /* ARGB 888 */
MDP_RGB_888, /* RGB 888 planar */
MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planar w/ Cr is in MSB */
MDP_YCRYCB_H2V1, /* YCrYCb interleave */
MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planar w/ Cr is in MSB */
MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planar w/ Cr is in MSB */
MDP_RGBA_8888, /* ARGB 888 */
MDP_BGRA_8888, /* ABGR 888 */
MDP_RGBX_8888, /* RGBX 888 */
MDP_IMGTYPE_LIMIT /* Non valid image type after this enum */
};
enum {
@ -57,20 +42,23 @@ enum {
};
/* flag values */
#define MDP_ROT_NOP 0
#define MDP_FLIP_LR 0x1
#define MDP_FLIP_UD 0x2
#define MDP_ROT_90 0x4
#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
#define MDP_ROT_MASK 0x7
#define MDP_DITHER 0x8
#define MDP_BLUR 0x10
#define MDP_ROT_NOP 0
#define MDP_FLIP_LR 0x1
#define MDP_FLIP_UD 0x2
#define MDP_ROT_90 0x4
#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
#define MDP_ROT_MASK 0x7
#define MDP_DITHER 0x8
#define MDP_BLUR 0x10
#define MDP_BLEND_FG_PREMULT 0x20000
#define MDP_DEINTERLACE 0x80000000
#define MDP_SHARPENING 0x40000000
#define MDP_TRANSP_NOP 0xffffffff
#define MDP_ALPHA_NOP 0xff
#define MDP_TRANSP_NOP 0xffffffff
#define MDP_ALPHA_NOP 0xff
/* drewis: added for android 4.0 */
#define MDP_BLIT_NON_CACHED 0x01000000
/* drewis: end */
struct mdp_rect {
uint32_t x;
@ -95,7 +83,6 @@ struct mdp_blit_req {
uint32_t alpha;
uint32_t transp_mask;
uint32_t flags;
int sharpening_strength; /* -127 <--> 127, default 64 */
};
struct mdp_blit_req_list {
@ -103,37 +90,4 @@ struct mdp_blit_req_list {
struct mdp_blit_req req[];
};
#ifdef CONFIG_MSM_MDP40
struct msmfb_data {
uint32_t offset;
int memory_id;
int id;
};
#define MSMFB_NEW_REQUEST -1
struct msmfb_overlay_data {
uint32_t id;
struct msmfb_data data;
};
struct msmfb_img {
uint32_t width;
uint32_t height;
uint32_t format;
};
struct mdp_overlay {
struct msmfb_img src;
struct mdp_rect src_rect;
struct mdp_rect dst_rect;
uint32_t z_order; /* stage number */
uint32_t is_fg; /* control alpha & transp */
uint32_t alpha;
uint32_t transp_mask;
uint32_t flags;
uint32_t id;
uint32_t user_data[8];
};
#endif
#endif //_MSM_MDP_H_
#endif /* _MSM_MDP_H_ */