Merge changes I5359aee9,Ia2e526aa into msm-3.0
* changes:
msm_serial_hs_lite: Use new clock framework apis
msm_serial_hs_lite: Cleanup regarding usage of clock enable/disable apis
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 0455878..bb4d971 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -65,6 +65,7 @@
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
+ u32 saved_dist_pri[DIV_ROUND_UP(1020, 4)];
u32 __percpu *saved_ppi_enable;
u32 __percpu *saved_ppi_conf;
#endif
@@ -79,6 +80,10 @@
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
+#ifdef CONFIG_CPU_PM
+static unsigned int saved_dist_ctrl, saved_cpu_ctrl;
+#endif
+
/* Address of GIC 0 CPU interface */
void __iomem *gic_cpu_base_addr __read_mostly;
@@ -151,6 +156,26 @@
return d->hwirq;
}
+#ifdef CONFIG_CPU_V7
+static const inline bool is_cpu_secure(void)
+{
+ unsigned int dscr;
+
+ asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (dscr));
+
+ /* BIT(18) - NS bit; 1 = NS; 0 = S */
+ if (BIT(18) & dscr)
+ return false;
+ else
+ return true;
+}
+#else
+static const inline bool is_cpu_secure(void)
+{
+ return false;
+}
+#endif
+
/*
* Routines to acknowledge, disable and enable interrupts
*/
@@ -506,6 +531,14 @@
writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
/*
+ * Set NS/S.
+ */
+ if (is_cpu_secure())
+ for (i = 32; i < gic_irqs; i += 32)
+ writel_relaxed(0xFFFFFFFF,
+ base + GIC_DIST_ISR + i * 4 / 32);
+
+ /*
* Set priority on all global interrupts.
*/
for (i = 32; i < gic_irqs; i += 4)
@@ -537,7 +570,11 @@
gic->max_irq = gic_irqs;
- writel_relaxed(1, base + GIC_DIST_CTRL);
+ if (is_cpu_secure())
+ writel_relaxed(3, base + GIC_DIST_CTRL);
+ else
+ writel_relaxed(1, base + GIC_DIST_CTRL);
+
mb();
}
@@ -554,6 +591,10 @@
writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
+ /* Set NS/S */
+ if (is_cpu_secure())
+ writel_relaxed(0xFFFFFFFF, dist_base + GIC_DIST_ISR);
+
/*
* Set priority on PPI and SGI interrupts
*/
@@ -561,7 +602,11 @@
writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
- writel_relaxed(1, base + GIC_CPU_CTRL);
+
+ if (is_cpu_secure())
+ writel_relaxed(0xF, base + GIC_CPU_CTRL);
+ else
+ writel_relaxed(1, base + GIC_CPU_CTRL);
mb();
}
@@ -587,6 +632,8 @@
if (!dist_base)
return;
+ saved_dist_ctrl = readl_relaxed(dist_base + GIC_DIST_CTRL);
+
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
gic_data[gic_nr].saved_spi_conf[i] =
readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
@@ -595,6 +642,10 @@
gic_data[gic_nr].saved_spi_target[i] =
readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+ for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
+ gic_data[gic_nr].saved_dist_pri[i] =
+ readl_relaxed(dist_base + GIC_DIST_PRI + i * 4);
+
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
gic_data[gic_nr].saved_spi_enable[i] =
readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
@@ -629,7 +680,7 @@
dist_base + GIC_DIST_CONFIG + i * 4);
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
- writel_relaxed(0xa0a0a0a0,
+ writel_relaxed(gic_data[gic_nr].saved_dist_pri[i],
dist_base + GIC_DIST_PRI + i * 4);
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
@@ -640,7 +691,7 @@
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
dist_base + GIC_DIST_ENABLE_SET + i * 4);
- writel_relaxed(1, dist_base + GIC_DIST_CTRL);
+ writel_relaxed(saved_dist_ctrl, dist_base + GIC_DIST_CTRL);
}
static void gic_cpu_save(unsigned int gic_nr)
@@ -659,6 +710,12 @@
if (!dist_base || !cpu_base)
return;
+ saved_cpu_ctrl = readl_relaxed(cpu_base + GIC_CPU_CTRL);
+
+ for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
+ gic_data[gic_nr].saved_dist_pri[i] = readl_relaxed(dist_base +
+ GIC_DIST_PRI + i * 4);
+
ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
@@ -694,10 +751,11 @@
writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
- writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
+ writel_relaxed(gic_data[gic_nr].saved_dist_pri[i],
+ dist_base + GIC_DIST_PRI + i * 4);
writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
- writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+ writel_relaxed(saved_cpu_ctrl, cpu_base + GIC_CPU_CTRL);
}
static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
@@ -884,12 +942,17 @@
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
int cpu;
+ unsigned long sgir;
unsigned long map = 0;
/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
map |= 1 << cpu_logical_map(cpu);
+ sgir = (map << 16) | irq;
+ if (is_cpu_secure())
+ sgir |= (1 << 15);
+
/*
* Ensure that stores to Normal memory are visible to the
* other CPUs before issuing the IPI.
@@ -897,11 +960,40 @@
dsb();
/* this always happens on GIC0 */
- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+ writel_relaxed(sgir,
+ gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
mb();
}
#endif
+void gic_set_irq_secure(unsigned int irq)
+{
+ unsigned int gicd_isr_reg, gicd_pri_reg;
+ unsigned int mask = 0xFFFFFF00;
+ struct gic_chip_data *gic_data = &gic_data[0];
+ struct irq_data *d = irq_get_irq_data(irq);
+
+ if (is_cpu_secure()) {
+ raw_spin_lock(&irq_controller_lock);
+ gicd_isr_reg = readl_relaxed(gic_dist_base(d) +
+ GIC_DIST_ISR + gic_irq(d) / 32 * 4);
+ gicd_isr_reg &= ~BIT(gic_irq(d) % 32);
+ writel_relaxed(gicd_isr_reg, gic_dist_base(d) +
+ GIC_DIST_ISR + gic_irq(d) / 32 * 4);
+ /* Also increase the priority of that irq */
+ gicd_pri_reg = readl_relaxed(gic_dist_base(d) +
+ GIC_DIST_PRI + (gic_irq(d) * 4 / 4));
+ gicd_pri_reg &= mask;
+ gicd_pri_reg |= 0x80; /* Priority of 0x80 > 0xA0 */
+ writel_relaxed(gicd_pri_reg, gic_dist_base(d) + GIC_DIST_PRI +
+ gic_irq(d) * 4 / 4);
+ mb();
+ raw_spin_unlock(&irq_controller_lock);
+ } else {
+ WARN(1, "Trying to run secure operation from Non-secure mode");
+ }
+}
+
/* before calling this function the interrupts should be disabled
* and the irq must be disabled at gic to avoid spurious interrupts */
bool gic_is_spi_pending(unsigned int irq)
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 76ff09c..3c87f8d 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -54,6 +54,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 3ddb0c9..cc33b8f 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -54,6 +54,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index eca2ffac..22cf652 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -74,6 +74,7 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
CONFIG_MSM_WATCHDOG=y
@@ -266,9 +267,7 @@
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_PMIC8XXX_PWRKEY=y
# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
@@ -329,9 +328,10 @@
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
-CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
+CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 18e9085..c38c161 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -74,6 +74,7 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
CONFIG_MSM_WATCHDOG=y
@@ -267,9 +268,7 @@
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_PMIC8XXX_PWRKEY=y
# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
@@ -330,6 +329,7 @@
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
+CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index d34f5dfb..543a4f9f 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -47,12 +47,13 @@
# CONFIG_MSM_SYSMON_COMM is not set
CONFIG_MSM_MODEM_8960=y
CONFIG_MSM_LPASS_8960=y
+CONFIG_MSM_RPM_LOG=y
+CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
CONFIG_MSM_WATCHDOG=y
CONFIG_MSM_DLOAD_MODE=y
-# CONFIG_MSM_JTAG_V7 is not set
CONFIG_SWP_EMULATE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -73,6 +74,8 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
@@ -83,7 +86,62 @@
# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
# CONFIG_INET6_XFRM_MODE_BEET is not set
# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_IP_SET=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_CFG80211=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
@@ -137,6 +195,8 @@
CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_BATTERY_MSM is not set
CONFIG_SENSORS_PM8XXX_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8960=y
@@ -168,8 +228,6 @@
CONFIG_USB_G_ANDROID=y
CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
-CONFIG_POWER_SUPPLY=y
-# CONFIG_BATTERY_MSM is not set
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
@@ -230,5 +288,3 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
-CONFIG_MSM_RPM_LOG=y
-CONFIG_MSM_RPM_STATS_LOG=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 8bfbcfa..5bb5139 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -22,6 +22,7 @@
#define GIC_DIST_CTRL 0x000
#define GIC_DIST_CTR 0x004
+#define GIC_DIST_ISR 0x080
#define GIC_DIST_ENABLE_SET 0x100
#define GIC_DIST_ENABLE_CLEAR 0x180
#define GIC_DIST_PENDING_SET 0x200
@@ -49,6 +50,7 @@
void gic_enable_ppi(unsigned int);
bool gic_is_spi_pending(unsigned int irq);
void gic_clear_spi_pending(unsigned int irq);
+void gic_set_irq_secure(unsigned int irq);
static inline void gic_init(unsigned int nr, int start,
void __iomem *dist , void __iomem *cpu)
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index a55ce3f..0ca5164 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -21,6 +21,8 @@
#define SCORPION_EVT_PREFIX 1
#define SCORPION_MAX_L1_REG 4
+#define SCORPION_EVTYPE_EVENT 0xfffff
+
static u32 scorpion_evt_type_base[] = {0x4c, 0x50, 0x54, 0x58, 0x5c};
enum scorpion_perf_common {
@@ -380,12 +382,14 @@
evtinfo->group_setval = 0x80000000 | (code << (group * 8));
evtinfo->groupcode = reg;
evtinfo->armv7_evt_type = scorpion_evt_type_base[reg] | group;
+
return evtinfo->armv7_evt_type;
}
if (scorpion_evt_type < SCORPION_EVT_START_IDX || scorpion_evt_type >=
(ARRAY_SIZE(scorpion_event) + SCORPION_EVT_START_IDX))
return -EINVAL;
+
idx = scorpion_evt_type - SCORPION_EVT_START_IDX;
if (scorpion_event[idx].scorpion_evt_type == scorpion_evt_type) {
evtinfo->group_setval = scorpion_event[idx].group_setval;
@@ -594,7 +598,7 @@
*/
if (idx != ARMV7_CYCLE_COUNTER) {
val = hwc->config_base;
- val &= ARMV7_EVTYPE_EVENT;
+ val &= SCORPION_EVTYPE_EVENT;
if (val > 0x40) {
event = get_scorpion_evtinfo(val, &evtinfo);
@@ -636,7 +640,7 @@
*/
if (idx != ARMV7_CYCLE_COUNTER) {
val = hwc->config_base;
- val &= ARMV7_EVTYPE_EVENT;
+ val &= SCORPION_EVTYPE_EVENT;
if (val < 0x40) {
armv7_pmnc_write_evtsel(idx, hwc->config_base);
@@ -676,7 +680,7 @@
{
int irq = *(unsigned int *)info;
- enable_percpu_irq(irq, 0);
+ enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
}
static void disable_irq_callback(void *info)
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 4328ac3..ea64ba6 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -468,9 +468,7 @@
static void ipi_timer(void)
{
struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
- irq_enter();
evt->event_handler(evt);
- irq_exit();
}
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
@@ -624,7 +622,9 @@
/* Wake up from WFI/WFE using SGI */
break;
case IPI_TIMER:
+ irq_enter();
ipi_timer();
+ irq_exit();
break;
case IPI_RESCHEDULE:
@@ -632,15 +632,21 @@
break;
case IPI_CALL_FUNC:
+ irq_enter();
generic_smp_call_function_interrupt();
+ irq_exit();
break;
case IPI_CALL_FUNC_SINGLE:
+ irq_enter();
generic_smp_call_function_single_interrupt();
+ irq_exit();
break;
case IPI_CPU_STOP:
+ irq_enter();
ipi_cpu_stop(cpu);
+ irq_exit();
break;
case IPI_CPU_BACKTRACE:
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 904839b9..0b0f733 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -126,6 +126,7 @@
select MSM_SPM_V1
select MSM_SCM if SMP
select MULTI_IRQ_HANDLER
+ select MSM_MULTIMEDIA_USE_ION
select MSM_PM8X60 if PM
config ARCH_MSM8960
@@ -257,6 +258,7 @@
select MSM_RPM_REGULATOR
select MULTI_IRQ_HANDLER
select MSM_PM8X60 if PM
+ select MSM_XO
config ARCH_MSM8625
bool "MSM8625"
@@ -449,7 +451,15 @@
default y
bool "MSM7627A QRD1"
help
- Support for the Qualcomm MSM7627A Refrence Design.
+ Support for the Qualcomm MSM7627A Reference Design.
+
+config MACH_MSM7627A_QRD3
+ depends on ARCH_MSM7X27A
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7627A QRD3"
+ help
+ Support for the Qualcomm MSM7627A Reference Design.
config MACH_MSM7627A_EVB
depends on ARCH_MSM7X27A
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 19a316e..b2f7c84d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -172,6 +172,7 @@
obj-$(CONFIG_ARCH_MSM8960) += rpm-regulator-8960.o
obj-$(CONFIG_ARCH_MSM9615) += rpm-regulator-9615.o
obj-$(CONFIG_ARCH_MSM8930) += rpm-regulator-8930.o
+obj-$(CONFIG_ARCH_APQ8064) += rpm-regulator-8960.o
endif
ifdef CONFIG_MSM_SUBSYSTEM_RESTART
@@ -217,6 +218,7 @@
obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7627A_QRD3) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
obj-$(CONFIG_MACH_MSM7627A_EVB) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
obj-$(CONFIG_ARCH_MSM8625) += devices-msm7x27a.o clock-pcom-lookup.o
obj-$(CONFIG_MACH_MSM8625_RUMI3) += board-msm7x27a.o
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 61c742d..470e836 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -463,81 +463,81 @@
static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 975000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 975000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 1000000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 1000000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1025000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1025000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1075000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1075000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1100000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1100000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1125000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1125000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 975000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1175000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1200000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1225000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1225000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1237500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1237500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1250000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1200000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1225000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1225000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1237500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1237500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1250000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom[] = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 925000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 950000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 950000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 975000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 975000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1025000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1050000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1050000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1075000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1075000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1125000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 925000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 950000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 950000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 975000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 975000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1025000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1025000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1050000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1050000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1075000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1075000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1125000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1125000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1150000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1150000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1175000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1175000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1187500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1187500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1200000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1150000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1150000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1175000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1175000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1187500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1187500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1200000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_8960_kraitv2_fast[] = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 875000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 875000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 900000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 925000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 975000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 975000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1000000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1000000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1025000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1025000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1075000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 875000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 900000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 900000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 925000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 925000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 975000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 975000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1000000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1000000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1025000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1025000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1075000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1075000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1100000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(19), 1100000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(19), 1125000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(19), 1125000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(19), 1137500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(19), 1137500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(19), 1150000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1100000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1100000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1125000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1125000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1137500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1137500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1150000 },
{ 0, { 0 } }
};
@@ -1298,10 +1298,10 @@
case CPU_DYING:
case CPU_DYING_FROZEN:
/*
- * On Krait v1, the primary and secondary muxes must be set
- * to QSB before L2 power collapse and restored after.
+ * On Krait v1 and 8064v1, the primary and secondary muxes must
+ * be set to QSB before L2 power collapse and restored after.
*/
- if (cpu_is_krait_v1()) {
+ if (cpu_is_krait_v1() || cpu_is_apq8064()) {
prev_sec_src[cpu] = get_sec_clk_src(&scalable[cpu]);
prev_pri_src[cpu] = get_pri_clk_src(&scalable[cpu]);
set_sec_clk_src(&scalable[cpu], SEC_SRC_SEL_QSB);
@@ -1324,7 +1324,7 @@
break;
case CPU_STARTING:
case CPU_STARTING_FROZEN:
- if (cpu_is_krait_v1()) {
+ if (cpu_is_krait_v1() || cpu_is_apq8064()) {
set_sec_clk_src(&scalable[cpu], prev_sec_src[cpu]);
set_pri_clk_src(&scalable[cpu], prev_pri_src[cpu]);
}
diff --git a/arch/arm/mach-msm/acpuclock-9615.c b/arch/arm/mach-msm/acpuclock-9615.c
index 35eb52b..8882f41 100644
--- a/arch/arm/mach-msm/acpuclock-9615.c
+++ b/arch/arm/mach-msm/acpuclock-9615.c
@@ -323,6 +323,11 @@
if (clocks[i].name) {
clocks[i].clk = clk_get_sys("acpu", clocks[i].name);
BUG_ON(IS_ERR(clocks[i].clk));
+ /*
+ * Prepare the PLLs because we enable/disable them
+ * in atomic context during power collapse/restore.
+ */
+ BUG_ON(clk_prepare(clocks[i].clk));
}
}
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 73758d0..5ead88c 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -28,10 +28,10 @@
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
/* prim = 1366 x 768 x 3(bpp) x 3(pages) */
-#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 3, 0x10000)
+#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 3, 0x10000)
#else
/* prim = 1366 x 768 x 3(bpp) x 2(pages) */
-#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 2, 0x10000)
+#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 2, 0x10000)
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@@ -58,22 +58,52 @@
#define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
#endif /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
+
static struct resource msm_fb_resources[] = {
{
.flags = IORESOURCE_DMA,
}
};
-#define SIMULATOR_PANAL_NAME "mipi_video_simulator"
-#define SIMULATOR_PANAL_NAME_LEN 20
+#define PANEL_NAME_MAX_LEN 30
#define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
-#define LVDS_CHIMEI_PANEL_NAME_LEN 16
+#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
+#define HDMI_PANEL_NAME "hdmi_msm"
+#define TVOUT_PANEL_NAME "tvout_msm"
static int msm_fb_detect_panel(const char *name)
{
- if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
- LVDS_CHIMEI_PANEL_NAME_LEN))
+ if (machine_is_apq8064_liquid()) {
+ if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
+ strnlen(LVDS_CHIMEI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+ !defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
+ if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+#endif
+ } else if (machine_is_apq8064_mtp()) {
+ if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+ } else if (machine_is_apq8064_cdp()) {
+ if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
+ strnlen(LVDS_CHIMEI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+ }
+
+ if (!strncmp(name, HDMI_PANEL_NAME,
+ strnlen(HDMI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
return 0;
+
return -ENODEV;
}
@@ -105,15 +135,15 @@
#define MDP_VSYNC_GPIO 0
static int mdp_core_clk_rate_table[] = {
- 266667000,
- 266667000,
- 266667000,
- 266667000,
+ 200000000,
+ 200000000,
+ 200000000,
+ 200000000,
};
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
- .mdp_core_clk_rate = 266667000,
+ .mdp_core_clk_rate = 200000000,
.mdp_core_clk_table = mdp_core_clk_rate_table,
.num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
.mdp_rev = MDP_REV_44,
@@ -136,9 +166,337 @@
#endif
}
+static bool dsi_power_on;
+static int mipi_dsi_panel_power(int on)
+{
+ static struct regulator *reg_lvs7, *reg_l2, *reg_l11, *reg_ext_3p3v;
+ static int gpio36, gpio25, gpio26, mpp3;
+ int rc;
+
+ pr_debug("%s: on=%d\n", __func__, on);
+
+ if (!dsi_power_on) {
+ reg_lvs7 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_vddio");
+ if (IS_ERR_OR_NULL(reg_lvs7)) {
+ pr_err("could not get 8921_lvs7, rc = %ld\n",
+ PTR_ERR(reg_lvs7));
+ return -ENODEV;
+ }
+
+ reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_pll_vdda");
+ if (IS_ERR_OR_NULL(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ reg_l11 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_avdd");
+ if (IS_ERR(reg_l11)) {
+ pr_err("could not get 8921_l11, rc = %ld\n",
+ PTR_ERR(reg_l11));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_l11, 3000000, 3000000);
+ if (rc) {
+ pr_err("set_voltage l11 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ if (machine_is_apq8064_liquid()) {
+ reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_vccs_3p3v");
+ if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
+ pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+ PTR_ERR(reg_ext_3p3v));
+ reg_ext_3p3v = NULL;
+ return -ENODEV;
+ }
+ mpp3 = PM8921_MPP_PM_TO_SYS(3);
+ rc = gpio_request(mpp3, "backlight_en");
+ if (rc) {
+ pr_err("request mpp3 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ }
+
+ gpio25 = PM8921_GPIO_PM_TO_SYS(25);
+ rc = gpio_request(gpio25, "disp_rst_n");
+ if (rc) {
+ pr_err("request gpio 25 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio26 = PM8921_GPIO_PM_TO_SYS(26);
+ rc = gpio_request(gpio26, "pwm_backlight_ctrl");
+ if (rc) {
+ pr_err("request gpio 26 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
+ rc = gpio_request(gpio36, "lcd1_pwr_en_n");
+ if (rc) {
+ pr_err("request gpio 36 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ dsi_power_on = true;
+ }
+
+ if (on) {
+ rc = regulator_enable(reg_lvs7);
+ if (rc) {
+ pr_err("enable lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_set_optimum_mode(reg_l11, 110000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l11 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l11);
+ if (rc) {
+ pr_err("enable l11 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ if (machine_is_apq8064_liquid()) {
+ rc = regulator_enable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("enable reg_ext_3p3v failed, rc=%d\n",
+ rc);
+ return -ENODEV;
+ }
+ gpio_set_value_cansleep(mpp3, 1);
+ }
+
+ gpio_set_value_cansleep(gpio36, 0);
+ gpio_set_value_cansleep(gpio25, 1);
+ } else {
+ gpio_set_value_cansleep(gpio25, 0);
+ gpio_set_value_cansleep(gpio36, 1);
+
+ if (machine_is_apq8064_liquid()) {
+ gpio_set_value_cansleep(mpp3, 0);
+
+ rc = regulator_disable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("disable reg_ext_3p3v failed, rc=%d\n",
+ rc);
+ return -ENODEV;
+ }
+ }
+
+ rc = regulator_disable(reg_lvs7);
+ if (rc) {
+ pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+ .dsi_power_save = mipi_dsi_panel_power,
+};
+
+static bool lvds_power_on;
+static int lvds_panel_power(int on)
+{
+ static struct regulator *reg_lvs7, *reg_l2, *reg_ext_3p3v;
+ static int gpio36, gpio26, mpp3;
+ int rc;
+
+ pr_debug("%s: on=%d\n", __func__, on);
+
+ if (!lvds_power_on) {
+ reg_lvs7 = regulator_get(&msm_lvds_device.dev,
+ "lvds_vdda");
+ if (IS_ERR_OR_NULL(reg_lvs7)) {
+ pr_err("could not get 8921_lvs7, rc = %ld\n",
+ PTR_ERR(reg_lvs7));
+ return -ENODEV;
+ }
+
+ reg_l2 = regulator_get(&msm_lvds_device.dev,
+ "lvds_pll_vdda");
+ if (IS_ERR_OR_NULL(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ reg_ext_3p3v = regulator_get(&msm_lvds_device.dev,
+ "lvds_vccs_3p3v");
+ if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
+ pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+ PTR_ERR(reg_ext_3p3v));
+ return -ENODEV;
+ }
+
+ gpio26 = PM8921_GPIO_PM_TO_SYS(26);
+ rc = gpio_request(gpio26, "pwm_backlight_ctrl");
+ if (rc) {
+ pr_err("request gpio 26 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
+ rc = gpio_request(gpio36, "lcd1_pwr_en_n");
+ if (rc) {
+ pr_err("request gpio 36 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ mpp3 = PM8921_MPP_PM_TO_SYS(3);
+ rc = gpio_request(mpp3, "backlight_en");
+ if (rc) {
+ pr_err("request mpp3 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ lvds_power_on = true;
+ }
+
+ if (on) {
+ rc = regulator_enable(reg_lvs7);
+ if (rc) {
+ pr_err("enable lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_enable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio_set_value_cansleep(gpio36, 0);
+ gpio_set_value_cansleep(mpp3, 1);
+ } else {
+ gpio_set_value_cansleep(mpp3, 0);
+ gpio_set_value_cansleep(gpio36, 1);
+
+ rc = regulator_disable(reg_lvs7);
+ if (rc) {
+ pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static struct lcdc_platform_data lvds_pdata = {
+ .lcdc_power_save = lvds_panel_power,
+};
+
+#define LPM_CHANNEL 2
+static int lvds_chimei_gpio[] = {LPM_CHANNEL};
+
+static struct lvds_panel_platform_data lvds_chimei_pdata = {
+ .gpio = lvds_chimei_gpio,
+};
+
+static struct platform_device lvds_chimei_panel_device = {
+ .name = "lvds_chimei_wxga",
+ .id = 0,
+ .dev = {
+ .platform_data = &lvds_chimei_pdata,
+ }
+};
+
+static int dsi2lvds_gpio[2] = {
+ LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
+ 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+};
+static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
+ .gpio_num = dsi2lvds_gpio,
+};
+
+static struct platform_device mipi_dsi2lvds_bridge_device = {
+ .name = "mipi_tc358764",
+ .id = 0,
+ .dev.platform_data = &mipi_dsi2lvds_pdata,
+};
+
+static int toshiba_gpio[] = {LPM_CHANNEL};
+static struct mipi_dsi_panel_platform_data toshiba_pdata = {
+ .gpio = toshiba_gpio,
+};
+
+static struct platform_device mipi_dsi_toshiba_panel_device = {
+ .name = "mipi_toshiba",
+ .id = 0,
+ .dev = {
+ .platform_data = &toshiba_pdata,
+ }
+};
+
void __init apq8064_init_fb(void)
{
platform_device_register(&msm_fb_device);
+ platform_device_register(&lvds_chimei_panel_device);
+
+ if (machine_is_apq8064_liquid())
+ platform_device_register(&mipi_dsi2lvds_bridge_device);
+ if (machine_is_apq8064_mtp())
+ platform_device_register(&mipi_dsi_toshiba_panel_device);
+
msm_fb_register_device("mdp", &mdp_pdata);
- msm_fb_register_device("lvds", NULL);
+ msm_fb_register_device("lvds", &lvds_pdata);
+ msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
}
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index de80a3e..62b7f17 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -104,6 +104,30 @@
.dir = GPIOMUX_OUT_LOW,
};
+static struct gpiomux_setting gsbi7_func1_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi7_func2_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi3_suspended_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting gsbi3_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
#ifdef CONFIG_USB_EHCI_MSM_HSIC
static struct gpiomux_setting hsic_act_cfg = {
.func = GPIOMUX_FUNC_1,
@@ -118,6 +142,66 @@
.dir = GPIOMUX_OUT_LOW,
};
+static struct gpiomux_setting cyts_resout_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_resout_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_sleep_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_sleep_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config cyts_gpio_configs[] __initdata = {
+ { /* TS INTERRUPT */
+ .gpio = 6,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_int_sus_cfg,
+ },
+ },
+ { /* TS SLEEP */
+ .gpio = 33,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_sleep_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
+ },
+ },
+ { /* TS RESOUT */
+ .gpio = 7,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_resout_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
+ },
+ },
+};
+
static struct msm_gpiomux_config apq8064_hsic_configs[] = {
{
.gpio = 88, /*HSIC_STROBE */
@@ -136,8 +220,46 @@
};
#endif
+static struct gpiomux_setting mxt_reset_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mxt_reset_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting mxt_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mxt_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
static struct msm_gpiomux_config apq8064_gsbi_configs[] __initdata = {
{
+ .gpio = 8, /* GSBI3 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
+ .gpio = 9, /* GSBI3 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
.gpio = 18, /* GSBI1 UART TX */
.settings = {
[GPIOMUX_SUSPENDED] = &gsbi1_uart_config,
@@ -199,6 +321,18 @@
[GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
},
},
+ {
+ .gpio = 82, /* GSBI7 UART2 TX */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi7_func2_cfg,
+ },
+ },
+ {
+ .gpio = 83, /* GSBI7 UART2 RX */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi7_func1_cfg,
+ },
+ },
};
static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
@@ -328,6 +462,23 @@
}
};
+static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
+ { /* TS INTERRUPT */
+ .gpio = 6,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mxt_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mxt_int_sus_cfg,
+ },
+ },
+ { /* TS RESET */
+ .gpio = 33,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mxt_reset_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mxt_reset_sus_cfg,
+ },
+ },
+};
+
void __init apq8064_init_gpiomux(void)
{
int rc;
@@ -362,8 +513,16 @@
msm_gpiomux_install(mdm_configs,
ARRAY_SIZE(mdm_configs));
+ if (machine_is_apq8064_mtp())
+ msm_gpiomux_install(cyts_gpio_configs,
+ ARRAY_SIZE(cyts_gpio_configs));
+
#ifdef CONFIG_USB_EHCI_MSM_HSIC
msm_gpiomux_install(apq8064_hsic_configs,
ARRAY_SIZE(apq8064_hsic_configs));
#endif
+
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ msm_gpiomux_install(apq8064_mxt_configs,
+ ARRAY_SIZE(apq8064_mxt_configs));
}
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index a8c5d48..0357c40 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -125,14 +125,14 @@
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 400000000,
- .bus_freq = 4,
- .io_fraction = 0,
+ .gpu_freq = 192000000,
+ .bus_freq = 2,
+ .io_fraction = 100,
},
{
- .gpu_freq = 320000000,
- .bus_freq = 3,
- .io_fraction = 33,
+ .gpu_freq = 192000000,
+ .bus_freq = 2,
+ .io_fraction = 100,
},
{
.gpu_freq = 1920000000,
@@ -140,8 +140,9 @@
.io_fraction = 100,
},
{
- .gpu_freq = 27000000,
- .bus_freq = 0,
+ .gpu_freq = 192000000,
+ .bus_freq = 2,
+ .io_fraction = 100,
},
},
.init_level = 0,
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 5204e48..02dfc5e 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -86,6 +86,13 @@
PM_GPIO_STRENGTH_##_strength, \
PM_GPIO_FUNC_NORMAL, 0, 0)
+#define PM8921_GPIO_OUTPUT_BUFCONF(_gpio, _val, _strength, _bufconf) \
+ PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT,\
+ PM_GPIO_OUT_BUF_##_bufconf, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_##_strength, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
#define PM8921_GPIO_INPUT(_gpio, _pull) \
PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
_pull, PM_GPIO_VIN_S4, \
@@ -106,12 +113,18 @@
/* Initial PM8921 GPIO configurations */
static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
+ PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
+ PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
+ PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
+ PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
};
/* Initial PM8XXX MPP configurations */
static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
+ PM8921_MPP_INIT(3, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
/* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
- PM8921_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
+ PM8921_MPP_INIT(7, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
+ PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
};
void __init apq8064_pm8xxx_gpio_mpp_init(void)
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index f3eebce..4e29feb 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -29,6 +29,8 @@
REGULATOR_SUPPLY("8921_l2", NULL),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-001a"),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-006c"),
+ REGULATOR_SUPPLY("lvds_pll_vdda", "lvds.0"),
+ REGULATOR_SUPPLY("dsi1_pll_vdda", "mipi_dsi.1"),
};
VREG_CONSUMERS(L3) = {
REGULATOR_SUPPLY("8921_l3", NULL),
@@ -62,6 +64,7 @@
};
VREG_CONSUMERS(L9) = {
REGULATOR_SUPPLY("8921_l9", NULL),
+ REGULATOR_SUPPLY("vdd", "3-0024"),
};
VREG_CONSUMERS(L10) = {
REGULATOR_SUPPLY("8921_l10", NULL),
@@ -69,6 +72,7 @@
};
VREG_CONSUMERS(L11) = {
REGULATOR_SUPPLY("8921_l11", NULL),
+ REGULATOR_SUPPLY("dsi1_avdd", "mipi_dsi.1"),
};
VREG_CONSUMERS(L12) = {
REGULATOR_SUPPLY("cam_vdig", "4-001a"),
@@ -97,6 +101,9 @@
};
VREG_CONSUMERS(L23) = {
REGULATOR_SUPPLY("8921_l23", NULL),
+ REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
+ REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.2"),
+
};
VREG_CONSUMERS(L24) = {
REGULATOR_SUPPLY("8921_l24", NULL),
@@ -106,6 +113,8 @@
REGULATOR_SUPPLY("8921_l25", NULL),
REGULATOR_SUPPLY("VDDD_CDC_D", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "tabla-slim"),
+ REGULATOR_SUPPLY("VDDD_CDC_D", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "tabla2x-slim"),
};
VREG_CONSUMERS(L26) = {
REGULATOR_SUPPLY("8921_l26", NULL),
@@ -113,9 +122,11 @@
};
VREG_CONSUMERS(L27) = {
REGULATOR_SUPPLY("8921_l27", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.2"),
};
VREG_CONSUMERS(L28) = {
REGULATOR_SUPPLY("8921_l28", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.1"),
};
VREG_CONSUMERS(S1) = {
REGULATOR_SUPPLY("8921_s1", NULL),
@@ -139,7 +150,13 @@
REGULATOR_SUPPLY("CDC_VDD_CP", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_TX", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_RX", "tabla-slim"),
+ REGULATOR_SUPPLY("VDDIO_CDC", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDD_CP", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_TX", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_RX", "tabla2x-slim"),
REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("vcc_i2c", "3-005b"),
+ REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
@@ -177,6 +194,8 @@
VREG_CONSUMERS(LVS7) = {
REGULATOR_SUPPLY("8921_lvs7", NULL),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
+ REGULATOR_SUPPLY("lvds_vdda", "lvds.0"),
+ REGULATOR_SUPPLY("dsi1_vddio", "mipi_dsi.1"),
};
VREG_CONSUMERS(USB_OTG) = {
REGULATOR_SUPPLY("8921_usb_otg", NULL),
@@ -199,10 +218,19 @@
VREG_CONSUMERS(EXT_5V) = {
REGULATOR_SUPPLY("ext_5v", NULL),
};
+VREG_CONSUMERS(EXT_MPP8) = {
+ REGULATOR_SUPPLY("ext_mpp8", NULL),
+};
VREG_CONSUMERS(EXT_3P3V) = {
REGULATOR_SUPPLY("ext_3p3v", NULL),
REGULATOR_SUPPLY("vdd_io", "spi0.2"),
REGULATOR_SUPPLY("mhl_ext_3p3v", "msm_otg"),
+ REGULATOR_SUPPLY("lvds_vccs_3p3v", "lvds.0"),
+ REGULATOR_SUPPLY("dsi1_vccs_3p3v", "mipi_dsi.1"),
+};
+VREG_CONSUMERS(EXT_TS_SW) = {
+ REGULATOR_SUPPLY("ext_ts_sw", NULL),
+ REGULATOR_SUPPLY("vdd_ana", "3-005b"),
};
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
@@ -328,6 +356,97 @@
.consumer_supplies = vreg_consumers_##_id, \
}
+#define RPM_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, _default_uV, \
+ _peak_uA, _avg_uA, _pull_down, _pin_ctrl, _freq, _pin_fn, \
+ _force_mode, _power_mode, _state, _sleep_selectable, \
+ _always_on, _supply_regulator, _system_uA) \
+ { \
+ .init_data = { \
+ .constraints = { \
+ .valid_modes_mask = _modes, \
+ .valid_ops_mask = _ops, \
+ .min_uV = _min_uV, \
+ .max_uV = _max_uV, \
+ .input_uV = _min_uV, \
+ .apply_uV = _apply_uV, \
+ .always_on = _always_on, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id), \
+ .consumer_supplies = vreg_consumers_##_id, \
+ .supply_regulator = _supply_regulator, \
+ }, \
+ .id = RPM_VREG_ID_PM8921_##_id, \
+ .default_uV = _default_uV, \
+ .peak_uA = _peak_uA, \
+ .avg_uA = _avg_uA, \
+ .pull_down_enable = _pull_down, \
+ .pin_ctrl = _pin_ctrl, \
+ .freq = RPM_VREG_FREQ_##_freq, \
+ .pin_fn = _pin_fn, \
+ .force_mode = _force_mode, \
+ .power_mode = _power_mode, \
+ .state = _state, \
+ .sleep_selectable = _sleep_selectable, \
+ .system_uA = _system_uA, \
+ }
+
+#define RPM_LDO(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+ _supply_regulator, _system_uA, _init_peak_uA) \
+ RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+ | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+ | REGULATOR_CHANGE_DRMS, 0, _max_uV, _init_peak_uA, 0, _pd, \
+ RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, _system_uA)
+
+#define RPM_SMPS(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+ _supply_regulator, _system_uA, _freq) \
+ RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+ | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+ | REGULATOR_CHANGE_DRMS, 0, _max_uV, _system_uA, 0, _pd, \
+ RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, _system_uA)
+
+#define RPM_VS(_id, _always_on, _pd, _sleep_selectable, _supply_regulator) \
+ RPM_INIT(_id, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, 0, 1000, 1000, _pd, \
+ RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, 0)
+
+#define RPM_NCP(_id, _always_on, _sleep_selectable, _min_uV, _max_uV, \
+ _supply_regulator, _freq) \
+ RPM_INIT(_id, _min_uV, _max_uV, 0, REGULATOR_CHANGE_VOLTAGE \
+ | REGULATOR_CHANGE_STATUS, 0, _max_uV, 1000, 1000, 0, \
+ RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, 0)
+
+/* Pin control initialization */
+#define RPM_PC_INIT(_id, _always_on, _pin_fn, _pin_ctrl, _supply_regulator) \
+ { \
+ .init_data = { \
+ .constraints = { \
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
+ .always_on = _always_on, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id##_PC), \
+ .consumer_supplies = vreg_consumers_##_id##_PC, \
+ .supply_regulator = _supply_regulator, \
+ }, \
+ .id = RPM_VREG_ID_PM8921_##_id##_PC, \
+ .pin_fn = RPM_VREG_PIN_FN_8960_##_pin_fn, \
+ .pin_ctrl = _pin_ctrl, \
+ }
+
/* GPIO regulator constraints */
struct gpio_regulator_platform_data
apq8064_gpio_regulator_pdata[] __devinitdata = {
@@ -335,6 +454,10 @@
GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", PM8921_MPP_PM_TO_SYS(7), NULL),
GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
APQ8064_EXT_3P3V_REG_EN_GPIO, NULL),
+ GPIO_VREG(EXT_TS_SW, "ext_ts_sw", "ext_ts_sw_en",
+ PM8921_GPIO_PM_TO_SYS(23), "ext_3p3v"),
+ GPIO_VREG(EXT_MPP8, "ext_mpp8", "ext_mpp8_en",
+ PM8921_MPP_PM_TO_SYS(8), NULL),
};
/* SAW regulator constraints */
@@ -354,69 +477,71 @@
struct pm8xxx_regulator_platform_data
msm8064_pm8921_regulator_pdata[] __devinitdata = {
/*
- * ID name always_on pd min_uV max_uV en_t supply
+ * ID name always_on pd min_uV max_uV en_t supply
* system_uA reg_ID
*/
- PM8XXX_SMPS(S1, "8921_s1", 1, 1, 1225000, 1225000, 500, NULL, 100000,
- 1),
- PM8XXX_SMPS(S2, "8921_s2", 0, 1, 1300000, 1300000, 500, NULL, 0, 2),
- PM8XXX_SMPS(S3, "8921_s3", 1, 1, 1150000, 1150000, 500, NULL, 100000,
- 3),
- PM8XXX_SMPS(S4, "8921_s4", 1, 1, 1800000, 1800000, 500, NULL, 100000,
- 4),
- PM8XXX_SMPS(S7, "8921_s7", 0, 1, 1300000, 1300000, 500, NULL, 100000,
- 5),
-
- PM8XXX_LDO(L1, "8921_l1", 1, 1, 1100000, 1100000, 200, "8921_s4", 0,
- 6),
- PM8XXX_LDO(L2, "8921_l2", 0, 1, 1200000, 1200000, 200, "8921_s4", 0,
- 7),
- PM8XXX_LDO(L3, "8921_l3", 0, 1, 3075000, 3075000, 200, NULL, 0, 8),
- PM8XXX_LDO(L4, "8921_l4", 1, 1, 1800000, 1800000, 200, NULL, 10000,
- 9),
- PM8XXX_LDO(L5, "8921_l5", 0, 1, 2950000, 2950000, 200, NULL, 0, 10),
- PM8XXX_LDO(L6, "8921_l6", 0, 1, 2950000, 2950000, 200, NULL, 0, 11),
- PM8XXX_LDO(L7, "8921_l7", 0, 1, 1850000, 2950000, 200, NULL, 0, 12),
- PM8XXX_LDO(L8, "8921_l8", 0, 1, 2800000, 2800000, 200, NULL, 0, 13),
- PM8XXX_LDO(L9, "8921_l9", 0, 1, 2850000, 2850000, 200, NULL, 0, 14),
- PM8XXX_LDO(L10, "8921_l10", 0, 1, 2900000, 2900000, 200, NULL, 0, 15),
- PM8XXX_LDO(L11, "8921_l11", 0, 1, 3000000, 3000000, 200, NULL, 0, 16),
- PM8XXX_LDO(L12, "8921_l12", 0, 1, 1200000, 1200000, 200, "8921_s4", 0,
- 17),
- PM8XXX_LDO(L14, "8921_l14", 0, 1, 1800000, 1800000, 200, NULL, 0, 18),
- PM8XXX_LDO(L15, "8921_l15", 0, 1, 1800000, 2950000, 200, NULL, 0, 19),
- PM8XXX_LDO(L16, "8921_l16", 0, 1, 2800000, 2800000, 200, NULL, 0, 20),
- PM8XXX_LDO(L17, "8921_l17", 0, 1, 2000000, 2000000, 200, NULL, 0, 21),
- PM8XXX_LDO(L18, "8921_l18", 0, 1, 1300000, 1800000, 200, "8921_s4", 0,
- 22),
- PM8XXX_LDO(L22, "8921_l22", 0, 1, 2600000, 2600000, 200, NULL, 0, 23),
- PM8XXX_LDO(L23, "8921_l23", 0, 1, 1800000, 1800000, 200, NULL, 0, 24),
- PM8XXX_NLDO1200(L24, "8921_l24", 1, 1, 1150000, 1150000, 200, "8921_s1",
- 10000, 25),
- PM8XXX_NLDO1200(L25, "8921_l25", 1, 1, 1225000, 1225000, 200, "8921_s1",
- 10000, 26),
PM8XXX_NLDO1200(L26, "8921_l26", 0, 1, 1050000, 1050000, 200, "8921_s7",
- 0, 27),
- PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 1100000, 1100000, 200, "8921_s7",
- 0, 28),
- PM8XXX_NLDO1200(L28, "8921_l28", 0, 1, 1050000, 1050000, 200, "8921_s7",
- 0, 29),
+ 0, 1),
- /* ID name always_on pd en_t supply reg_ID */
- PM8XXX_VS(LVS1, "8921_lvs1", 0, 1, 0, "8921_s4", 30),
- PM8XXX_VS300(LVS2, "8921_lvs2", 0, 1, 0, "8921_s1", 31),
- PM8XXX_VS(LVS3, "8921_lvs3", 0, 1, 0, "8921_s4", 32),
- PM8XXX_VS(LVS4, "8921_lvs4", 0, 1, 0, "8921_s4", 33),
- PM8XXX_VS(LVS5, "8921_lvs5", 0, 1, 0, "8921_s4", 34),
- PM8XXX_VS(LVS6, "8921_lvs6", 0, 1, 0, "8921_s4", 35),
- PM8XXX_VS(LVS7, "8921_lvs7", 1, 1, 0, "8921_s4", 36),
+ /* ID name always_on pd en_t supply reg_ID */
+ PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 0, 0, "ext_5v", 2),
+ PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, "ext_5v", 3),
+};
- PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 0, 0, "ext_5v", 37),
- PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, "ext_5v", 38),
+static struct rpm_regulator_init_data
+apq8064_rpm_regulator_init_data[] __devinitdata = {
+ /* ID a_on pd ss min_uV max_uV supply sys_uA freq */
+ RPM_SMPS(S1, 1, 1, 0, 1225000, 1225000, NULL, 100000, 3p20),
+ RPM_SMPS(S2, 0, 1, 0, 1300000, 1300000, NULL, 0, 1p60),
+ RPM_SMPS(S3, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80),
+ RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60),
+ RPM_SMPS(S7, 0, 1, 0, 1300000, 1300000, NULL, 100000, 3p20),
- /* ID name always_on min_uV max_uV en_t supply reg_ID */
- PM8XXX_NCP(NCP, "8921_ncp", 0, 1800000, 1800000, 200, "8921_l6", 39),
+ /* ID a_on pd ss min_uV max_uV supply sys_uA init_ip */
+ RPM_LDO(L1, 1, 1, 0, 1100000, 1100000, "8921_s4", 0, 10000),
+ RPM_LDO(L2, 0, 1, 0, 1200000, 1200000, "8921_s4", 0, 0),
+ RPM_LDO(L3, 0, 1, 0, 3075000, 3075000, NULL, 0, 0),
+ RPM_LDO(L4, 1, 1, 0, 1800000, 1800000, NULL, 10000, 10000),
+ RPM_LDO(L5, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
+ RPM_LDO(L6, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
+ RPM_LDO(L7, 0, 1, 0, 1850000, 2950000, NULL, 0, 0),
+ RPM_LDO(L8, 0, 1, 0, 2800000, 2800000, NULL, 0, 0),
+ RPM_LDO(L9, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
+ RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL, 0, 0),
+ RPM_LDO(L11, 0, 1, 0, 3000000, 3000000, NULL, 0, 0),
+ RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8921_s4", 0, 0),
+ RPM_LDO(L14, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
+ RPM_LDO(L15, 0, 1, 0, 1800000, 2950000, NULL, 0, 0),
+ RPM_LDO(L16, 0, 1, 0, 2800000, 2800000, NULL, 0, 0),
+ RPM_LDO(L17, 0, 1, 0, 2000000, 2000000, NULL, 0, 0),
+ RPM_LDO(L18, 0, 1, 0, 1300000, 1800000, "8921_s4", 0, 0),
+ RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL, 0, 0),
+ RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
+ RPM_LDO(L24, 0, 1, 1, 750000, 1150000, "8921_s1", 10000, 10000),
+ RPM_LDO(L25, 1, 1, 0, 1225000, 1225000, "8921_s1", 10000, 10000),
+ RPM_LDO(L27, 0, 1, 0, 1100000, 1100000, "8921_s7", 0, 0),
+ RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7", 0, 0),
+
+ /* ID a_on pd ss supply */
+ RPM_VS(LVS1, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS2, 0, 1, 0, "8921_s1"),
+ RPM_VS(LVS3, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS4, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS5, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS6, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS7, 1, 1, 1, "8921_s4"),
+
+ /* ID a_on ss min_uV max_uV supply freq */
+ RPM_NCP(NCP, 0, 0, 1800000, 1800000, "8921_l6", 1p60),
};
int msm8064_pm8921_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm8064_pm8921_regulator_pdata);
+
+struct rpm_regulator_platform_data apq8064_rpm_regulator_pdata __devinitdata = {
+ .init_data = apq8064_rpm_regulator_init_data,
+ .num_regulators = ARRAY_SIZE(apq8064_rpm_regulator_init_data),
+ .version = RPM_VREG_VERSION_8960,
+ .vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
+ .vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
+};
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 8a3b958..0d187a9 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -230,6 +230,10 @@
.sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
.pin_data = &mmc_slot_pin_data[SDCC3],
.vreg_data = &mmc_slot_vreg_data[SDCC3],
+ .status_gpio = 26,
+ .status_irq = MSM_GPIO_TO_INT(26),
+ .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ .is_status_gpio_active_low = 1,
};
static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
#else
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index febc55d..2afd3cc 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -24,6 +24,8 @@
#include <linux/platform_data/qcom_crypto_device.h>
#include <linux/ion.h>
#include <linux/memory.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/cyttsp.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -525,6 +527,207 @@
},
};
+/* configuration data for mxt1386e using V2.1 firmware */
+static const u8 mxt1386e_config_data_v2_1[] = {
+ /* T6 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T38 Object */
+ 14, 0, 0, 24, 1, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T7 Object */
+ 100, 16, 50,
+ /* T8 Object */
+ 25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
+ /* T9 Object */
+ 131, 0, 0, 26, 42, 0, 32, 80, 2, 5,
+ 0, 5, 5, 0, 10, 30, 10, 10, 255, 2,
+ 85, 5, 10, 10, 10, 10, 135, 55, 70, 40,
+ 10, 5, 0, 0, 0,
+ /* T18 Object */
+ 0, 0,
+ /* T24 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* T25 Object */
+ 3, 0, 60, 115, 156, 99,
+ /* T27 Object */
+ 0, 0, 0, 0, 0, 0, 0,
+ /* T40 Object */
+ 0, 0, 0, 0, 0,
+ /* T42 Object */
+ 2, 0, 255, 0, 255, 0, 0, 0, 0, 0,
+ /* T43 Object */
+ 0, 0, 0, 0, 0, 0, 0, 64, 0, 8,
+ 16,
+ /* T46 Object */
+ 64, 0, 20, 20, 0, 0, 0, 0, 0,
+ /* T47 Object */
+ 0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
+ /* T48 Object */
+ 31, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+ 48, 40, 0, 10, 10, 0, 0, 100, 10, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 52, 0, 12, 0, 17, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T56 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 99, 33, 0, 149, 24, 193, 255, 255, 255,
+ 255,
+};
+
+#define MXT_TS_GPIO_IRQ 6
+#define MXT_TS_PWR_EN_GPIO PM8921_GPIO_PM_TO_SYS(23)
+#define MXT_TS_RESET_GPIO 33
+
+static struct mxt_config_info mxt_config_array[] = {
+ {
+ .config = mxt1386e_config_data_v2_1,
+ .config_length = ARRAY_SIZE(mxt1386e_config_data_v2_1),
+ .family_id = 0xA0,
+ .variant_id = 0x7,
+ .version = 0x21,
+ .build = 0xAA,
+ },
+};
+
+static struct mxt_platform_data mxt_platform_data = {
+ .config_array = mxt_config_array,
+ .config_array_size = ARRAY_SIZE(mxt_config_array),
+ .x_size = 1365,
+ .y_size = 767,
+ .irqflags = IRQF_TRIGGER_FALLING,
+ .i2c_pull_up = true,
+ .reset_gpio = MXT_TS_RESET_GPIO,
+ .irq_gpio = MXT_TS_GPIO_IRQ,
+};
+
+static struct i2c_board_info mxt_device_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
+ .platform_data = &mxt_platform_data,
+ .irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
+ },
+};
+#define CYTTSP_TS_GPIO_IRQ 6
+#define CYTTSP_TS_GPIO_RESOUT 7
+#define CYTTSP_TS_GPIO_SLEEP 33
+
+static ssize_t tma340_vkeys_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 200,
+ __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":73:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":230:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":389:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":544:1120:97:97"
+ "\n");
+}
+
+static struct kobj_attribute tma340_vkeys_attr = {
+ .attr = {
+ .mode = S_IRUGO,
+ },
+ .show = &tma340_vkeys_show,
+};
+
+static struct attribute *tma340_properties_attrs[] = {
+ &tma340_vkeys_attr.attr,
+ NULL
+};
+
+static struct attribute_group tma340_properties_attr_group = {
+ .attrs = tma340_properties_attrs,
+};
+
+static int cyttsp_platform_init(struct i2c_client *client)
+{
+ int rc = 0;
+ static struct kobject *tma340_properties_kobj;
+
+ tma340_vkeys_attr.attr.name = "virtualkeys.cyttsp-i2c";
+ tma340_properties_kobj = kobject_create_and_add("board_properties",
+ NULL);
+ if (tma340_properties_kobj)
+ rc = sysfs_create_group(tma340_properties_kobj,
+ &tma340_properties_attr_group);
+ if (!tma340_properties_kobj || rc)
+ pr_err("%s: failed to create board_properties\n",
+ __func__);
+
+ return 0;
+}
+
+static struct cyttsp_regulator cyttsp_regulator_data[] = {
+ {
+ .name = "vdd",
+ .min_uV = CY_TMA300_VTG_MIN_UV,
+ .max_uV = CY_TMA300_VTG_MAX_UV,
+ .hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+ .lpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+ },
+ {
+ .name = "vcc_i2c",
+ .min_uV = CY_I2C_VTG_MIN_UV,
+ .max_uV = CY_I2C_VTG_MAX_UV,
+ .hpm_load_uA = CY_I2C_CURR_UA,
+ .lpm_load_uA = CY_I2C_CURR_UA,
+ },
+};
+
+static struct cyttsp_platform_data cyttsp_pdata = {
+ .panel_maxx = 634,
+ .panel_maxy = 1166,
+ .disp_maxx = 599,
+ .disp_maxy = 1023,
+ .disp_minx = 0,
+ .disp_miny = 0,
+ .flags = 0x01,
+ .gen = CY_GEN3,
+ .use_st = CY_USE_ST,
+ .use_mt = CY_USE_MT,
+ .use_hndshk = CY_SEND_HNDSHK,
+ .use_trk_id = CY_USE_TRACKING_ID,
+ .use_sleep = CY_USE_DEEP_SLEEP_SEL,
+ .use_gestures = CY_USE_GESTURES,
+ .fw_fname = "cyttsp_8064_mtp.hex",
+ /* change act_intrvl to customize the Active power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .act_intrvl = CY_ACT_INTRVL_DFLT,
+ /* change tch_tmout to customize the touch timeout for the
+ * Active power state for Operating mode
+ */
+ .tch_tmout = CY_TCH_TMOUT_DFLT,
+ /* change lp_intrvl to customize the Low Power power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .lp_intrvl = CY_LP_INTRVL_DFLT,
+ .sleep_gpio = CYTTSP_TS_GPIO_SLEEP,
+ .resout_gpio = CYTTSP_TS_GPIO_RESOUT,
+ .irq_gpio = CYTTSP_TS_GPIO_IRQ,
+ .regulator_info = cyttsp_regulator_data,
+ .num_regulators = ARRAY_SIZE(cyttsp_regulator_data),
+ .init = cyttsp_platform_init,
+ .correct_fw_ver = 17,
+};
+
+static struct i2c_board_info cyttsp_info[] __initdata = {
+ {
+ I2C_BOARD_INFO(CY_I2C_NAME, 0x24),
+ .platform_data = &cyttsp_pdata,
+ .irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ),
+ },
+};
+
#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -664,12 +867,6 @@
msm_mpm_irq_extn_init(data);
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
(void *)MSM_QGIC_CPU_BASE);
-
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
- mb();
}
static struct platform_device msm8064_device_saw_regulator_core0 = {
@@ -1091,6 +1288,15 @@
},
};
+static struct platform_device apq8064_device_ext_mpp8_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_MPP_PM_TO_SYS(8),
+ .dev = {
+ .platform_data
+ = &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_MPP8],
+ },
+};
+
static struct platform_device apq8064_device_ext_3p3v_vreg __devinitdata = {
.name = GPIO_REGULATOR_DEV_NAME,
.id = APQ8064_EXT_3P3V_REG_EN_GPIO,
@@ -1100,13 +1306,32 @@
},
};
+static struct platform_device apq8064_device_ext_ts_sw_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_GPIO_PM_TO_SYS(23),
+ .dev = {
+ .platform_data
+ = &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_TS_SW],
+ },
+};
+
+static struct platform_device apq8064_device_rpm_regulator __devinitdata = {
+ .name = "rpm-regulator",
+ .id = -1,
+ .dev = {
+ .platform_data = &apq8064_rpm_regulator_pdata,
+ },
+};
+
static struct platform_device *common_devices[] __initdata = {
&apq8064_device_dmov,
+ &apq8064_device_qup_i2c_gsbi3,
&apq8064_device_qup_i2c_gsbi4,
&apq8064_device_qup_spi_gsbi5,
- &apq8064_slim_ctrl,
&apq8064_device_ext_5v_vreg,
+ &apq8064_device_ext_mpp8_vreg,
&apq8064_device_ext_3p3v_vreg,
+ &apq8064_device_ext_ts_sw_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
&msm_device_smd_apq8064,
@@ -1173,7 +1398,7 @@
&msm_bus_8064_mm_fabric,
&msm_bus_8064_sys_fpb,
&msm_bus_8064_cpss_fpb,
- &msm_device_vidc,
+ &apq8064_msm_device_vidc,
&msm_8960_riva,
&msm_8960_q6_lpass,
&msm_gss,
@@ -1194,6 +1419,7 @@
static struct platform_device *cdp_devices[] __initdata = {
&apq8064_device_uart_gsbi1,
+ &apq8064_device_uart_gsbi7,
&msm_device_sps_apq8064,
};
@@ -1226,6 +1452,11 @@
/* add more slimbus slaves as needed */
};
+static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+};
+
static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi4_pdata = {
.clk_freq = 100000,
.src_clk_rate = 24000000,
@@ -1233,6 +1464,8 @@
static void __init apq8064_i2c_init(void)
{
+ apq8064_device_qup_i2c_gsbi3.dev.platform_data =
+ &apq8064_i2c_qup_gsbi3_pdata;
apq8064_device_qup_i2c_gsbi4.dev.platform_data =
&apq8064_i2c_qup_gsbi4_pdata;
}
@@ -1266,15 +1499,74 @@
msm_clock_init(&apq8064_clock_init_data);
}
+#define I2C_SURF 1
+#define I2C_FFA (1 << 1)
+#define I2C_RUMI (1 << 2)
+#define I2C_SIM (1 << 3)
+#define I2C_LIQUID (1 << 4)
+
+struct i2c_registry {
+ u8 machs;
+ int bus;
+ struct i2c_board_info *info;
+ int len;
+};
+
+static struct i2c_registry apq8064_i2c_devices[] __initdata = {
+ {
+ I2C_SURF | I2C_LIQUID,
+ APQ_8064_GSBI3_QUP_I2C_BUS_ID,
+ mxt_device_info,
+ ARRAY_SIZE(mxt_device_info),
+ },
+ {
+ I2C_FFA,
+ APQ_8064_GSBI3_QUP_I2C_BUS_ID,
+ cyttsp_info,
+ ARRAY_SIZE(cyttsp_info),
+ },
+};
+
+static void __init register_i2c_devices(void)
+{
+ u8 mach_mask = 0;
+ int i;
+
+ /* Build the matching 'supported_machs' bitmask */
+ if (machine_is_apq8064_cdp())
+ mach_mask = I2C_SURF;
+ else if (machine_is_apq8064_mtp())
+ mach_mask = I2C_FFA;
+ else if (machine_is_apq8064_liquid())
+ mach_mask = I2C_LIQUID;
+ else if (machine_is_apq8064_rumi3())
+ mach_mask = I2C_RUMI;
+ else if (machine_is_apq8064_sim())
+ mach_mask = I2C_SIM;
+ else
+ pr_err("unmatched machine ID in register_i2c_devices\n");
+
+ /* Run the array and install devices as appropriate */
+ for (i = 0; i < ARRAY_SIZE(apq8064_i2c_devices); ++i) {
+ if (apq8064_i2c_devices[i].machs & mach_mask)
+ i2c_register_board_info(apq8064_i2c_devices[i].bus,
+ apq8064_i2c_devices[i].info,
+ apq8064_i2c_devices[i].len);
+ }
+}
+
static void __init apq8064_common_init(void)
{
if (socinfo_init() < 0)
pr_err("socinfo_init() failed!\n");
BUG_ON(msm_rpm_init(&apq8064_rpm_data));
BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
+ regulator_suppress_info_printing();
+ platform_device_register(&apq8064_device_rpm_regulator);
apq8064_clock_init();
apq8064_init_gpiomux();
apq8064_i2c_init();
+ register_i2c_devices();
apq8064_device_qup_spi_gsbi5.dev.platform_data =
&apq8064_qup_spi_gsbi5_pdata;
@@ -1287,6 +1579,12 @@
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
apq8064_pm8xxx_gpio_mpp_init();
apq8064_init_mmc();
+
+ if (machine_is_apq8064_mtp()) {
+ mdm_8064_device.dev.platform_data = &mdm_platform_data;
+ platform_device_register(&mdm_8064_device);
+ }
+ platform_device_register(&apq8064_slim_ctrl);
slim_register_board_info(apq8064_slim_devices,
ARRAY_SIZE(apq8064_slim_devices));
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
@@ -1297,11 +1595,6 @@
msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
msm_pm_data);
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-
- if (machine_is_apq8064_mtp()) {
- mdm_8064_device.dev.platform_data = &mdm_platform_data;
- platform_device_register(&mdm_8064_device);
- }
}
static void __init apq8064_allocate_memory_regions(void)
@@ -1335,7 +1628,10 @@
ethernet_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+ apq8064_init_fb();
apq8064_init_gpu();
+ platform_add_devices(msm_footswitch_devices,
+ msm_num_footswitch_devices);
}
MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
@@ -1364,6 +1660,7 @@
.handle_irq = gic_handle_irq,
.timer = &msm_timer,
.init_machine = apq8064_cdp_init,
+ .init_early = apq8064_allocate_memory_regions,
MACHINE_END
MACHINE_START(APQ8064_MTP, "QCT APQ8064 MTP")
@@ -1373,6 +1670,7 @@
.handle_irq = gic_handle_irq,
.timer = &msm_timer,
.init_machine = apq8064_cdp_init,
+ .init_early = apq8064_allocate_memory_regions,
MACHINE_END
MACHINE_START(APQ8064_LIQUID, "QCT APQ8064 LIQUID")
@@ -1382,5 +1680,6 @@
.handle_irq = gic_handle_irq,
.timer = &msm_timer,
.init_machine = apq8064_cdp_init,
+ .init_early = apq8064_allocate_memory_regions,
MACHINE_END
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index e1451f5..d401f4c 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -18,6 +18,7 @@
#include <linux/mfd/pm8xxx/pm8821.h>
#include <mach/msm_memtypes.h>
#include <mach/irqs.h>
+#include <mach/rpm-regulator.h>
/* Macros assume PMIC GPIOs and MPPs start at 1 */
#define PM8921_GPIO_BASE NR_GPIO_IRQS
@@ -37,12 +38,17 @@
#define GPIO_VREG_ID_EXT_5V 0
#define GPIO_VREG_ID_EXT_3P3V 1
+#define GPIO_VREG_ID_EXT_TS_SW 2
+#define GPIO_VREG_ID_EXT_MPP8 3
#define APQ8064_EXT_3P3V_REG_EN_GPIO 77
extern struct gpio_regulator_platform_data
apq8064_gpio_regulator_pdata[] __devinitdata;
+extern struct rpm_regulator_platform_data
+ apq8064_rpm_regulator_pdata __devinitdata;
+
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0;
@@ -58,6 +64,7 @@
extern struct msm_camera_board_info apq8064_camera_board_info;
void apq8064_init_cam(void);
+#define APQ_8064_GSBI3_QUP_I2C_BUS_ID 3
#define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
void apq8064_init_fb(void);
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 30c912e..e0bc723 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -495,6 +495,34 @@
};
#endif
+static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
+ {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+ {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+ {"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+ {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
+};
+
+static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
+ .mount_angle = 0,
+ .cam_vreg = msm_8930_s5k3l1yx_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8930_s5k3l1yx_vreg),
+ .gpio_conf = &msm_8930_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k3l1yx_data = {
+ .sensor_name = "s5k3l1yx",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_s5k3l1yx,
+ .sensor_platform_info = &sensor_board_info_s5k3l1yx,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+};
+
void __init msm8930_init_cam(void)
{
msm_gpiomux_install(msm8930_cam_common_configs,
@@ -527,6 +555,10 @@
I2C_BOARD_INFO("mt9m114", 0x48),
.platform_data = &msm_camera_sensor_mt9m114_data,
},
+ {
+ I2C_BOARD_INFO("s5k3l1yx", 0x20),
+ .platform_data = &msm_camera_sensor_s5k3l1yx_data,
+ },
#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
{
I2C_BOARD_INFO("sc628a", 0x6E),
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 262616f..9175c75 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -228,6 +228,11 @@
pr_err("enable l2 failed, rc=%d\n", rc);
return -ENODEV;
}
+ usleep(10000);
+ gpio_set_value(DISP_RST_GPIO, 1);
+ usleep(10);
+ gpio_set_value(DISP_RST_GPIO, 0);
+ usleep(20);
gpio_set_value(DISP_RST_GPIO, 1);
} else {
@@ -412,7 +417,7 @@
#else
static int mdp_core_clk_rate_table[] = {
85330000,
- 85330000,
+ 128000000,
160000000,
200000000,
};
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index 2f59d9d..3f9f976 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -225,6 +225,45 @@
.thermal_levels = ARRAY_SIZE(pm8921_therm_mitigation),
};
+#define PM8038_WLED_MAX_CURRENT 25
+
+static struct led_info pm8038_led_info[] = {
+ [0] = {
+ .name = "wled",
+ },
+};
+
+static struct led_platform_data pm8038_led_core_pdata = {
+ .num_leds = ARRAY_SIZE(pm8038_led_info),
+ .leds = pm8038_led_info,
+};
+
+static struct wled_config_data wled_cfg = {
+ .dig_mod_gen_en = true,
+ .cs_out_en = true,
+ .ctrl_delay_us = 0,
+ .op_fdbck = true,
+ .ovp_val = WLED_OVP_32V,
+ .boost_curr_lim = WLED_CURR_LIMIT_525mA,
+ .num_strings = 1,
+};
+
+static struct pm8xxx_led_config pm8038_led_configs[] = {
+ [0] = {
+ .id = PM8XXX_ID_WLED,
+ .mode = PM8XXX_LED_MODE_MANUAL,
+ .max_current = PM8038_WLED_MAX_CURRENT,
+ .default_state = 1,
+ .wled_cfg = &wled_cfg,
+ },
+};
+
+static struct pm8xxx_led_platform_data pm8xxx_leds_pdata = {
+ .led_core = &pm8038_led_core_pdata,
+ .configs = pm8038_led_configs,
+ .num_configs = ARRAY_SIZE(pm8038_led_configs),
+};
+
static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
.r_sense = 10,
};
@@ -252,6 +291,7 @@
.charger_pdata = &pm8921_chg_pdata,
.bms_pdata = &pm8921_bms_pdata,
.adc_pdata = &pm8xxx_adc_pdata,
+ .leds_pdata = &pm8xxx_leds_pdata,
.ccadc_pdata = &pm8xxx_ccadc_pdata,
};
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 0208631..2f9fdcd 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -33,6 +33,7 @@
REGULATOR_SUPPLY("mipi_csi_vdd", "4-001a"),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-006c"),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-0048"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "4-0020"),
};
VREG_CONSUMERS(L3) = {
REGULATOR_SUPPLY("8038_l3", NULL),
@@ -68,6 +69,8 @@
REGULATOR_SUPPLY("cam_vaf", "4-001a"),
REGULATOR_SUPPLY("cam_vaf", "4-006c"),
REGULATOR_SUPPLY("cam_vaf", "4-0048"),
+ REGULATOR_SUPPLY("cam_vana", "4-0020"),
+ REGULATOR_SUPPLY("cam_vaf", "4-0020"),
};
VREG_CONSUMERS(L10) = {
REGULATOR_SUPPLY("8038_l10", NULL),
@@ -88,6 +91,7 @@
REGULATOR_SUPPLY("cam_vdig", "4-001a"),
REGULATOR_SUPPLY("cam_vdig", "4-006c"),
REGULATOR_SUPPLY("cam_vdig", "4-0048"),
+ REGULATOR_SUPPLY("cam_vdig", "4-0020"),
};
VREG_CONSUMERS(L14) = {
REGULATOR_SUPPLY("8038_l14", NULL),
@@ -108,6 +112,7 @@
REGULATOR_SUPPLY("cam_vio", "4-001a"),
REGULATOR_SUPPLY("cam_vio", "4-006c"),
REGULATOR_SUPPLY("cam_vio", "4-0048"),
+ REGULATOR_SUPPLY("cam_vio", "4-0020"),
};
VREG_CONSUMERS(L19) = {
REGULATOR_SUPPLY("8038_l19", NULL),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 3858e63..90cc3c5 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -40,6 +40,7 @@
#include <linux/ks8851.h>
#include <linux/i2c/isa1200.h>
#include <linux/gpio_keys.h>
+#include <linux/memory.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -429,12 +430,9 @@
if (high - low <= bank_size)
return;
- msm8930_reserve_info.low_unstable_address = low + bank_size;
- /* To avoid overflow of u32 compute max_unstable_size
- * by first subtracting low from mb->start)
- * */
- msm8930_reserve_info.max_unstable_size = (mb->start - low) +
- mb->size - bank_size;
+ msm8930_reserve_info.low_unstable_address = mb->start -
+ MIN_MEMORY_BLOCK_SIZE + mb->size;
+ msm8930_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
msm8930_reserve_info.bank_size = bank_size;
pr_info("low unstable address %lx max size %lx bank size %lx\n",
@@ -902,12 +900,6 @@
msm_mpm_irq_extn_init(data);
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
(void *)MSM_QGIC_CPU_BASE);
-
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
- mb();
}
static void __init msm8930_init_buses(void)
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 2995679..23c4928 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -219,6 +219,18 @@
.ab = 0,
.ib = 0,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
};
static struct msm_bus_vectors cam_preview_vectors[] = {
@@ -240,6 +252,18 @@
.ab = 0,
.ib = 0,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
};
static struct msm_bus_vectors cam_video_vectors[] = {
@@ -261,6 +285,18 @@
.ab = 0,
.ib = 0,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
};
static struct msm_bus_vectors cam_snapshot_vectors[] = {
@@ -282,6 +318,18 @@
.ab = 540000000,
.ib = 1350000000,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
};
static struct msm_bus_vectors cam_zsl_vectors[] = {
@@ -303,6 +351,18 @@
.ab = 540000000,
.ib = 1350000000,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
};
static struct msm_bus_paths cam_bus_client_config[] = {
@@ -500,6 +560,34 @@
};
#endif
+static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
+ {"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
+ {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
+ {"cam_vio", REG_VS, 0, 0, 0},
+ {"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+};
+
+static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
+ .mount_angle = 0,
+ .cam_vreg = msm_8960_s5k3l1yx_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8960_s5k3l1yx_vreg),
+ .gpio_conf = &msm_8960_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_s5k3l1yx_data = {
+ .sensor_name = "s5k3l1yx",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_s5k3l1yx,
+ .sensor_platform_info = &sensor_board_info_s5k3l1yx,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+};
+
static struct pm8xxx_mpp_config_data privacy_light_on_config = {
.type = PM8XXX_MPP_TYPE_SINK,
.level = PM8XXX_MPP_CS_OUT_5MA,
@@ -580,6 +668,10 @@
I2C_BOARD_INFO("mt9m114", 0x48),
.platform_data = &msm_camera_sensor_mt9m114_data,
},
+ {
+ I2C_BOARD_INFO("s5k3l1yx", 0x20),
+ .platform_data = &msm_camera_sensor_s5k3l1yx_data,
+ },
#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
{
I2C_BOARD_INFO("sc628a", 0x6E),
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index f9bc8fc..aa8477e 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -81,6 +81,8 @@
}
};
+static void set_mdp_clocks_for_liquid_wuxga(void);
+
static int msm_fb_detect_panel(const char *name)
{
if (machine_is_msm8960_liquid()) {
@@ -88,8 +90,10 @@
if (SOCINFO_VERSION_MAJOR(ver) == 3) {
if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
+ PANEL_NAME_MAX_LEN))) {
+ set_mdp_clocks_for_liquid_wuxga();
return 0;
+ }
} else {
if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
@@ -617,7 +621,7 @@
#else
static int mdp_core_clk_rate_table[] = {
85330000,
- 85330000,
+ 128000000,
160000000,
200000000,
};
@@ -643,6 +647,24 @@
#endif
};
+/**
+ * Set MDP clocks to high frequency to avoid DSI underflow
+ * when using high resolution 1200x1920 WUXGA panel.
+ */
+static void set_mdp_clocks_for_liquid_wuxga(void)
+{
+ int i;
+
+ mdp_ui_vectors[0].ab = 2000000000;
+ mdp_ui_vectors[0].ib = 2000000000;
+
+ mdp_pdata.mdp_core_clk_rate = 200000000;
+
+ for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
+ mdp_core_clk_rate_table[i] = 200000000;
+
+}
+
void __init msm8960_mdp_writeback(struct memtype_reserve* reserve_table)
{
mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
@@ -681,9 +703,11 @@
};
#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
-static int dsi2lvds_gpio[2] = {
+static int dsi2lvds_gpio[4] = {
0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
- 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+ 0x1F08, /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+ GPIO_LIQUID_EXPANDER_BASE+6, /* TN Enable */
+ GPIO_LIQUID_EXPANDER_BASE+7, /* TN Mode */
};
static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 04376bc..744709c 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -95,9 +95,12 @@
PM8XXX_GPIO_INPUT(16, PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
/* External regulator shared by display and touchscreen on LiQUID */
PM8XXX_GPIO_OUTPUT(17, 0), /* DISP 3.3 V Boost */
+ PM8XXX_GPIO_OUTPUT(18, 1), /* TABLA SPKR_LEFT_EN */
+ PM8XXX_GPIO_OUTPUT(19, 1), /* TABLA SPKR_RIGHT_EN */
PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH), /* Backlight Enable */
PM8XXX_GPIO_DISABLE(22), /* Disable NFC */
PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
+ PM8XXX_GPIO_OUTPUT_FUNC(25, 0, PM_GPIO_FUNC_2), /* TN_CLK */
PM8XXX_GPIO_INPUT(26, PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
PM8XXX_GPIO_OUTPUT(43, PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
PM8XXX_GPIO_OUTPUT(42, 0), /* USB 5V reg enable */
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 6819d5d..0f05af5 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -33,6 +33,7 @@
REGULATOR_SUPPLY("mipi_csi_vdd", "4-001a"),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-006c"),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-0048"),
+ REGULATOR_SUPPLY("mipi_csi_vdd", "4-0020"),
};
VREG_CONSUMERS(L3) = {
REGULATOR_SUPPLY("8921_l3", NULL),
@@ -74,12 +75,14 @@
REGULATOR_SUPPLY("cam_vana", "4-001a"),
REGULATOR_SUPPLY("cam_vana", "4-006c"),
REGULATOR_SUPPLY("cam_vana", "4-0048"),
+ REGULATOR_SUPPLY("cam_vana", "4-0020"),
};
VREG_CONSUMERS(L12) = {
REGULATOR_SUPPLY("8921_l12", NULL),
REGULATOR_SUPPLY("cam_vdig", "4-001a"),
REGULATOR_SUPPLY("cam_vdig", "4-006c"),
REGULATOR_SUPPLY("cam_vdig", "4-0048"),
+ REGULATOR_SUPPLY("cam_vdig", "4-0020"),
};
VREG_CONSUMERS(L14) = {
REGULATOR_SUPPLY("8921_l14", NULL),
@@ -93,6 +96,7 @@
REGULATOR_SUPPLY("cam_vaf", "4-001a"),
REGULATOR_SUPPLY("cam_vaf", "4-006c"),
REGULATOR_SUPPLY("cam_vaf", "4-0048"),
+ REGULATOR_SUPPLY("cam_vaf", "4-0020"),
};
VREG_CONSUMERS(L17) = {
REGULATOR_SUPPLY("8921_l17", NULL),
@@ -207,6 +211,7 @@
REGULATOR_SUPPLY("cam_vio", "4-001a"),
REGULATOR_SUPPLY("cam_vio", "4-006c"),
REGULATOR_SUPPLY("cam_vio", "4-0048"),
+ REGULATOR_SUPPLY("cam_vio", "4-0020"),
};
VREG_CONSUMERS(LVS6) = {
REGULATOR_SUPPLY("8921_lvs6", NULL),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 9985b32..76a27ff 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -301,10 +301,6 @@
#endif
}
-static void __init reserve_fmem_memory(void)
-{
-}
-
static int msm8960_paddr_to_memtype(unsigned int paddr)
{
return MEMTYPE_EBI1;
@@ -315,11 +311,13 @@
static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
.permission_type = IPT_TYPE_MM_CARVEOUT,
.align = PAGE_SIZE,
+ .reusable = 1,
};
static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
.permission_type = IPT_TYPE_MFC_SHAREDMEM,
.align = PAGE_SIZE,
+ .reusable = 0,
};
static struct ion_co_heap_pdata co_ion_pdata = {
@@ -411,9 +409,8 @@
.dev = { .platform_data = &fmem_pdata },
};
-static void reserve_ion_memory(void)
+static void __init adjust_mem_for_liquid(void)
{
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
unsigned int i;
if (!pmem_param_set && machine_is_msm8960_liquid()) {
@@ -427,12 +424,99 @@
}
}
}
- msm8960_reserve_table[MEMTYPE_EBI1].size += msm_ion_cp_mm_size;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+}
+
+static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
+ unsigned long size)
+{
+ msm8960_reserve_table[mem_type].size += size;
+}
+
+static __init const struct ion_platform_heap *find_ion_heap(int heap_id)
+{
+ unsigned int i;
+ for (i = 0; i < ion_pdata.nr; ++i) {
+ const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+ if (heap->id == heap_id)
+ return (const struct ion_platform_heap *) heap;
+ }
+ return 0;
+}
+
+/**
+ * Reserve memory for ION and calculate amount of reusable memory for fmem.
+ * We only reserve memory for heaps that are not reusable. However, we only
+ * support one reusable heap at the moment so we ignore the reusable flag for
+ * other than the first heap with reusable flag set. Also handle special case
+ * for adjacent heap when the adjacent heap is adjacent to a reusable heap.
+ */
+static void __init reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ unsigned int i;
+ unsigned int reusable_count = 0;
+
+ adjust_mem_for_liquid();
+ fmem_pdata.size = 0;
+ fmem_pdata.reserved_size = 0;
+
+ /* We only support 1 reusable heap. Check if more than one heap
+ * is specified as reusable and set as non-reusable if found.
+ */
+ for (i = 0; i < ion_pdata.nr; ++i) {
+ const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+ if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
+ struct ion_cp_heap_pdata *data = heap->extra_data;
+
+ reusable_count += (data->reusable) ? 1 : 0;
+
+ if (data->reusable && reusable_count > 1) {
+ pr_err("%s: Too many heaps specified as "
+ "reusable. Heap %s was not configured "
+ "as reusable.\n", __func__, heap->name);
+ data->reusable = 0;
+ }
+ }
+ }
+
+ for (i = 0; i < ion_pdata.nr; ++i) {
+ int reusable = 0;
+ int adjacent_heap_id = INVALID_HEAP_ID;
+ int adj_reusable = 0;
+ const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+
+ if (heap->extra_data) {
+ switch (heap->type) {
+ case ION_HEAP_TYPE_CP:
+ reusable = ((struct ion_cp_heap_pdata *)
+ heap->extra_data)->reusable;
+ break;
+ case ION_HEAP_TYPE_CARVEOUT:
+ adjacent_heap_id = ((struct ion_co_heap_pdata *)
+ heap->extra_data)->adjacent_mem_id;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (adjacent_heap_id != INVALID_HEAP_ID) {
+ const struct ion_platform_heap *adj_heap =
+ find_ion_heap(adjacent_heap_id);
+ if (adj_heap) {
+ adj_reusable = ((struct ion_cp_heap_pdata *)
+ adj_heap->extra_data)->reusable;
+ if (adj_reusable)
+ fmem_pdata.reserved_size += heap->size;
+ }
+ }
+
+ if (!reusable && !adj_reusable)
+ reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
+ else
+ fmem_pdata.size += heap->size;
+ }
#endif
}
@@ -446,7 +530,6 @@
size_pmem_devices();
reserve_pmem_memory();
reserve_ion_memory();
- reserve_fmem_memory();
reserve_mdp_memory();
}
@@ -898,12 +981,6 @@
msm_mpm_irq_extn_init(data);
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
(void *)MSM_QGIC_CPU_BASE);
-
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
- mb();
}
static void __init msm8960_init_buses(void)
@@ -945,12 +1022,54 @@
0x23, 0x83,/* set source impedance sdjusment */
-1};
+#ifdef CONFIG_MSM_BUS_SCALING
+/* Bandwidth requests (zero) if no vote placed */
+static struct msm_bus_vectors usb_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+/* Bus bandwidth requests in Bytes/sec */
+static struct msm_bus_vectors usb_max_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 60000000, /* At least 480Mbps on bus. */
+ .ib = 960000000, /* MAX bursts rate */
+ },
+};
+
+static struct msm_bus_paths usb_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(usb_init_vectors),
+ usb_init_vectors,
+ },
+ {
+ ARRAY_SIZE(usb_max_vectors),
+ usb_max_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata usb_bus_scale_pdata = {
+ usb_bus_scale_usecases,
+ ARRAY_SIZE(usb_bus_scale_usecases),
+ .name = "usb",
+};
+#endif
+
static struct msm_otg_platform_data msm_otg_pdata = {
.mode = USB_OTG,
.otg_control = OTG_PMIC_CONTROL,
.phy_type = SNPS_28NM_INTEGRATED_PHY,
.pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
.power_budget = 750,
+#ifdef CONFIG_MSM_BUS_SCALING
+ .bus_scale_table = &usb_bus_scale_pdata,
+#endif
};
#endif
@@ -1839,6 +1958,7 @@
&msm_bus_sys_fpb,
&msm_bus_cpss_fpb,
&msm_pcm,
+ &msm_multi_ch_pcm,
&msm_pcm_routing,
&msm_cpudai0,
&msm_cpudai1,
@@ -1890,6 +2010,7 @@
&msm_device_hsusb_host,
&android_usb_device,
&msm_pcm,
+ &msm_multi_ch_pcm,
&msm_pcm_routing,
&msm_cpudai0,
&msm_cpudai1,
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 84a8a42..1f19bf6 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -31,6 +31,7 @@
#include <mach/gpio.h>
#include <mach/msm_spi.h>
#include <mach/msm_bus_board.h>
+#include <mach/msm_xo.h>
#include "timer.h"
#include "devices.h"
#include "board-9615.h"
@@ -568,6 +569,7 @@
msm9615_i2c_init();
regulator_suppress_info_printing();
platform_device_register(&msm9615_device_rpm_regulator);
+ msm_xo_init();
msm_clock_init(&msm9615_clock_init_data);
msm9615_init_buses();
msm9615_device_qup_spi_gsbi3.dev.platform_data =
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 1bfb759..b4b0b9a 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -233,12 +233,6 @@
void __init msm_copper_init_irq(void)
{
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
- mb();
-
of_irq_init(irq_match);
}
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index 5acfcd5b..c70b30e 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -935,6 +935,9 @@
int i, rc = 0;
struct device *dev;
+ if (machine_is_msm7627a_qrd3())
+ return;
+
gpio_bt_config();
i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index e3f668f..c0b1d16 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -796,6 +796,8 @@
ARRAY_SIZE(camera_devices_qrd));
} else if (machine_is_msm7627a_evb())
return;
+ else if (machine_is_msm7627a_qrd3())
+ return;
else
platform_add_devices(camera_devices_msm,
ARRAY_SIZE(camera_devices_msm));
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 030c129..011a4d4 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -226,6 +226,9 @@
} else if (machine_is_msm7627a_qrd1()) {
if (!strncmp(name, "mipi_video_truly_wvga", 21))
ret = 0;
+ } else if (machine_is_msm7627a_evb()) {
+ if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
+ ret = 0;
}
#if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
@@ -303,6 +306,18 @@
}
};
+static struct msm_panel_common_pdata mipi_NT35510_pdata = {
+ .pmic_backlight = NULL,/*mipi_NT35510_set_bl,*/
+};
+
+static struct platform_device mipi_dsi_NT35510_panel_device = {
+ .name = "mipi_NT35510",
+ .id = 0,
+ .dev = {
+ .platform_data = &mipi_NT35510_pdata,
+ }
+};
+
static struct platform_device *msm_fb_devices[] __initdata = {
&msm_fb_device,
&lcdc_toshiba_panel_device,
@@ -317,7 +332,8 @@
};
static struct platform_device *evb_fb_devices[] __initdata = {
-
+ &msm_fb_device,
+ &mipi_dsi_NT35510_panel_device,
};
void __init msm_msm7627a_allocate_memory_regions(void)
@@ -487,12 +503,60 @@
return rc;
}
+#define GPIO_QRD3_LCD_BRDG_RESET_N 85
+#define GPIO_QRD3_LCD_BACKLIGHT_EN 96
+#define GPIO_QRD3_LCD_EXT_2V85_EN 35
+#define GPIO_QRD3_LCD_EXT_1V8_EN 40
+
+static unsigned qrd3_mipi_dsi_gpio[] = {
+ GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0, GPIO_CFG_OUTPUT,
+ GPIO_CFG_NO_PULL,
+ GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BRDG_RESET_N */
+ GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0, GPIO_CFG_OUTPUT,
+ GPIO_CFG_NO_PULL,
+ GPIO_CFG_2MA), /* GPIO_QRD3_LCD_BACKLIGHT_EN */
+ GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0, GPIO_CFG_OUTPUT,
+ GPIO_CFG_NO_PULL,
+ GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_2V85_EN */
+ GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0, GPIO_CFG_OUTPUT,
+ GPIO_CFG_NO_PULL,
+ GPIO_CFG_2MA), /* GPIO_QRD3_LCD_EXT_1V8_EN */
+};
+
+static int msm_fb_dsi_client_qrd3_reset(void)
+{
+ int rc = 0;
+
+ rc = gpio_request(GPIO_QRD3_LCD_BRDG_RESET_N, "qrd3_lcd_brdg_reset_n");
+ if (rc < 0) {
+ pr_err("failed to request qrd3 lcd brdg reset_n\n");
+ return rc;
+ }
+
+ rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("Failed to enable LCD Bridge reset enable\n");
+ return rc;
+ }
+
+ rc = gpio_direction_output(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+ if (rc < 0) {
+ pr_err("Failed GPIO bridge Reset\n");
+ gpio_free(GPIO_QRD3_LCD_BRDG_RESET_N);
+ return rc;
+ }
+
+ return rc;
+}
+
static int msm_fb_dsi_client_reset(void)
{
int rc = 0;
if (machine_is_msm7627a_qrd1())
rc = msm_fb_dsi_client_qrd1_reset();
+ else if (machine_is_msm7627a_evb())
+ rc = msm_fb_dsi_client_qrd3_reset();
else
rc = msm_fb_dsi_client_msm_reset();
@@ -650,7 +714,7 @@
gpio_set_value_cansleep(QRD_GPIO_BACKLIGHT_EN, !!on);
- if (!on) {
+ if (on) {
gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 1);
msleep(20);
gpio_set_value_cansleep(GPIO_LCDC_BRDG_RESET_N, 0);
@@ -662,12 +726,99 @@
return rc;
}
+static int qrd3_dsi_gpio_initialized;
+
+static int mipi_dsi_panel_qrd3_power(int on)
+{
+ int rc = 0;
+
+ if (!qrd3_dsi_gpio_initialized) {
+ rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
+ "qrd3_gpio_bkl_en");
+ if (rc < 0)
+ return rc;
+
+ rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
+ return rc;
+ }
+ rc = gpio_direction_output(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
+ if (rc < 0) {
+ pr_err("failed to enable backlight\n");
+ gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
+ return rc;
+ }
+
+ rc = gpio_request(GPIO_QRD3_LCD_EXT_2V85_EN,
+ "qrd3_gpio_ext_2v85_en");
+ if (rc < 0)
+ return rc;
+
+ rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_2V85_EN tlmm config\n");
+ return rc;
+ }
+
+ rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_2V85_EN, 1);
+ if (rc < 0) {
+ pr_err("failed to enable external 2V85\n");
+ gpio_free(GPIO_QRD3_LCD_EXT_2V85_EN);
+ return rc;
+ }
+
+ rc = gpio_request(GPIO_QRD3_LCD_EXT_1V8_EN,
+ "qrd3_gpio_ext_1v8_en");
+ if (rc < 0)
+ return rc;
+
+ rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0,
+ GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
+ if (rc < 0) {
+ pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_1V8_EN tlmm config\n");
+ return rc;
+ }
+
+ rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_1V8_EN, 1);
+ if (rc < 0) {
+ pr_err("failed to enable external 1v8\n");
+ gpio_free(GPIO_QRD3_LCD_EXT_1V8_EN);
+ return rc;
+ }
+
+ qrd3_dsi_gpio_initialized = 1;
+ }
+
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
+
+ if (on) {
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+ msleep(20);
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
+ msleep(20);
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
+ msleep(20);
+ }
+
+ return rc;
+}
+
static int mipi_dsi_panel_power(int on)
{
int rc = 0;
if (machine_is_msm7627a_qrd1())
rc = mipi_dsi_panel_qrd1_power(on);
+ else if (machine_is_msm7627a_evb())
+ rc = mipi_dsi_panel_qrd3_power(on);
else
rc = mipi_dsi_panel_msm_power(on);
return rc;
@@ -692,6 +843,8 @@
else if (machine_is_msm7627a_evb())
platform_add_devices(evb_fb_devices,
ARRAY_SIZE(evb_fb_devices));
+ else if (machine_is_msm7627a_qrd3())
+ return;
else
platform_add_devices(msm_fb_devices,
ARRAY_SIZE(msm_fb_devices));
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 8eb92a4..d5d8edc 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -1588,15 +1588,17 @@
static struct msm_pm_platform_data msm7x25_pm_data[MSM_PM_SLEEP_MODE_NR] = {
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency = 16000,
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)].latency = 16000,
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency = 12000,
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)]
+ .latency = 12000,
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency = 2000,
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)]
+ .latency = 2000,
};
static struct msm_pm_platform_data msm7x27_pm_data[MSM_PM_SLEEP_MODE_NR] = {
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
@@ -1605,7 +1607,7 @@
.residency = 20000,
},
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
@@ -1614,7 +1616,7 @@
.residency = 20000,
},
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index d2add18..51da14b 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio_event.h>
+#include <linux/memblock.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -325,7 +326,7 @@
};
#endif
static struct msm_pm_platform_data msm7x27a_pm_data[MSM_PM_SLEEP_MODE_NR] = {
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
@@ -333,7 +334,7 @@
.latency = 16000,
.residency = 20000,
},
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
@@ -341,7 +342,7 @@
.latency = 12000,
.residency = 20000,
},
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 0,
@@ -349,7 +350,7 @@
.latency = 2000,
.residency = 0,
},
- [MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
@@ -799,6 +800,11 @@
msm_reserve();
}
+static void __init msm8625_reserve(void)
+{
+ memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+}
+
static void __init msm_device_i2c_init(void)
{
if (machine_is_msm8625_rumi3()) {
@@ -1239,6 +1245,7 @@
MACHINE_START(MSM8625_RUMI3, "QCT MSM8625 RUMI3")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm8625_map_io,
+ .reserve = msm8625_reserve,
.init_irq = msm8625_init_irq,
.init_machine = msm8625_rumi3_init,
.timer = &msm_timer,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index e0b3c49..47a4605 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -2907,7 +2907,7 @@
};
static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR] = {
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
@@ -2915,7 +2915,7 @@
.latency = 8594,
.residency = 23740,
},
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
@@ -2923,7 +2923,7 @@
.latency = 4594,
.residency = 23740,
},
- [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
#ifdef CONFIG_MSM_STANDALONE_POWER_COLLAPSE
.idle_supported = 1,
.suspend_supported = 1,
@@ -2938,7 +2938,7 @@
.latency = 500,
.residency = 6000,
},
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 0,
@@ -2946,7 +2946,7 @@
.latency = 443,
.residency = 1098,
},
- [MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
.idle_supported = 1,
.suspend_supported = 1,
.idle_enabled = 1,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 29f5fac..74ba1b36 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2697,7 +2697,7 @@
#define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
#define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE
-#define MSM_ION_SF_SIZE 0x1800000 /* 24MB */
+#define MSM_ION_SF_SIZE 0x4000000 /* 64MB */
#define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
#define MSM_ION_MM_SIZE 0x3600000 /* (54MB) */
@@ -9572,7 +9572,7 @@
#ifdef CONFIG_FB_MSM_MIPI_DSI
int mdp_core_clk_rate_table[] = {
85330000,
- 85330000,
+ 128000000,
160000000,
200000000,
};
@@ -9586,7 +9586,7 @@
#else
int mdp_core_clk_rate_table[] = {
59080000,
- 85330000,
+ 128000000,
128000000,
200000000,
};
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 1222b67..0427632 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -684,6 +684,10 @@
&asoc_msm_dai1,
};
+static struct platform_device *qrd3_devices[] __initdata = {
+ &msm_device_nand,
+};
+
static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
static int __init pmem_kernel_ebi1_size_setup(char *p)
{
@@ -1016,6 +1020,16 @@
return platform_device_register(&msm_wlan_ar6000_pm_device);
}
+static void add_platform_devices(void)
+{
+ platform_add_devices(qrd_common_devices,
+ ARRAY_SIZE(qrd_common_devices));
+
+ if (machine_is_msm7627a_qrd3())
+ platform_add_devices(qrd3_devices,
+ ARRAY_SIZE(qrd3_devices));
+}
+
#define UART1DM_RX_GPIO 45
static void __init msm_qrd_init(void)
{
@@ -1035,8 +1049,7 @@
msm_device_gadget_peripheral.dev.platform_data =
&msm_gadget_pdata;
- platform_add_devices(qrd_common_devices,
- ARRAY_SIZE(qrd_common_devices));
+ add_platform_devices();
/* Ensure ar6000pm device is registered before MMC/SDC */
msm_qrd_init_ar6000pm();
@@ -1075,6 +1088,16 @@
.init_early = qrd7627a_init_early,
.handle_irq = vic_handle_irq,
MACHINE_END
+MACHINE_START(MSM7627A_QRD3, "QRD MSM7627a QRD3")
+ .boot_params = PHYS_OFFSET + 0x100,
+ .map_io = msm_common_io_init,
+ .reserve = msm7627a_reserve,
+ .init_irq = msm_init_irq,
+ .init_machine = msm_qrd_init,
+ .timer = &msm_timer,
+ .init_early = qrd7627a_init_early,
+ .handle_irq = vic_handle_irq,
+MACHINE_END
MACHINE_START(MSM7627A_EVB, "QRD MSM7627a EVB")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 47e51a3..493a210 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -44,6 +44,7 @@
#define ADM0_PBUS_CLK_CTL_REG REG(0x2208)
#define CE1_HCLK_CTL_REG REG(0x2720)
#define CE1_CORE_CLK_CTL_REG REG(0x2724)
+#define PRNG_CLK_NS_REG REG(0x2E80)
#define CE3_HCLK_CTL_REG REG(0x36C4)
#define CE3_CORE_CLK_CTL_REG REG(0x36CC)
#define CE3_CLK_SRC_NS_REG REG(0x36C0)
@@ -4846,45 +4847,46 @@
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
- CLK_DUMMY("bus_clk", AFAB_CLK, "msm_apps_fab", 0),
- CLK_DUMMY("bus_a_clk", AFAB_A_CLK, "msm_apps_fab", 0),
- CLK_DUMMY("bus_clk", SFAB_CLK, "msm_sys_fab", 0),
- CLK_DUMMY("bus_a_clk", SFAB_A_CLK, "msm_sys_fab", 0),
- CLK_DUMMY("bus_clk", SFPB_CLK, "msm_sys_fpb", 0),
- CLK_DUMMY("bus_a_clk", SFPB_A_CLK, "msm_sys_fpb", 0),
- CLK_DUMMY("bus_clk", MMFAB_CLK, "msm_mm_fab", 0),
- CLK_DUMMY("bus_a_clk", MMFAB_A_CLK, "msm_mm_fab", 0),
- CLK_DUMMY("bus_clk", CFPB_CLK, "msm_cpss_fpb", 0),
- CLK_DUMMY("bus_a_clk", CFPB_A_CLK, "msm_cpss_fpb", 0),
- CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
- CLK_DUMMY("mem_a_clk", EBI1_A_CLK, "msm_bus", 0),
+ CLK_LOOKUP("bus_clk", afab_clk.c, "msm_apps_fab"),
+ CLK_LOOKUP("bus_a_clk", afab_a_clk.c, "msm_apps_fab"),
+ CLK_LOOKUP("bus_clk", cfpb_clk.c, "msm_cpss_fpb"),
+ CLK_LOOKUP("bus_a_clk", cfpb_a_clk.c, "msm_cpss_fpb"),
+ CLK_LOOKUP("bus_clk", sfab_clk.c, "msm_sys_fab"),
+ CLK_LOOKUP("bus_a_clk", sfab_a_clk.c, "msm_sys_fab"),
+ CLK_LOOKUP("bus_clk", sfpb_clk.c, "msm_sys_fpb"),
+ CLK_LOOKUP("bus_a_clk", sfpb_a_clk.c, "msm_sys_fpb"),
+ CLK_LOOKUP("bus_clk", mmfab_clk.c, "msm_mm_fab"),
+ CLK_LOOKUP("bus_a_clk", mmfab_a_clk.c, "msm_mm_fab"),
+ CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
+ CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
- CLK_DUMMY("ebi1_clk", EBI1_CLK, NULL, 0),
- CLK_DUMMY("dfab_clk", DFAB_CLK, NULL, 0),
- CLK_DUMMY("dfab_a_clk", DFAB_A_CLK, NULL, 0),
- CLK_DUMMY("bus_clk", MMFPB_CLK, NULL, 0),
- CLK_DUMMY("bus_a_clk", MMFPB_A_CLK, NULL, 0),
+ CLK_LOOKUP("ebi1_clk", ebi1_clk.c, ""),
+ CLK_LOOKUP("dfab_clk", dfab_clk.c, ""),
+ CLK_LOOKUP("dfab_a_clk", dfab_a_clk.c, ""),
+ CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, ""),
+ CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, "clock-8960"),
+ CLK_LOOKUP("cfpb_a_clk", cfpb_a_clk.c, "clock-8960"),
CLK_LOOKUP("core_clk", gp0_clk.c, ""),
CLK_LOOKUP("core_clk", gp1_clk.c, ""),
CLK_LOOKUP("core_clk", gp2_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, "msm_serial_hsl.0"),
+ CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, "msm_serial_hsl.1"),
CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi4_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi6_uart_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi1_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi2_qup_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi3_qup_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi3_qup_clk.c, "qup_i2c.3"),
CLK_LOOKUP("core_clk", gsbi4_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi5_qup_clk.c, "spi_qsd.0"),
CLK_LOOKUP("core_clk", gsbi6_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi7_qup_clk.c, ""),
CLK_LOOKUP("core_clk", pdm_clk.c, ""),
CLK_LOOKUP("mem_clk", pmem_clk.c, "msm_sps"),
- CLK_DUMMY("core_clk", PRNG_CLK, "msm_rng.0", OFF),
+ CLK_LOOKUP("core_clk", prng_clk.c, "msm_rng.0"),
CLK_LOOKUP("core_clk", sdc1_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("core_clk", sdc2_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("core_clk", sdc3_clk.c, "msm_sdcc.3"),
@@ -4908,13 +4910,13 @@
CLK_LOOKUP("ce3_core_src_clk", ce3_src_clk.c, "qce.0"),
CLK_LOOKUP("ce3_core_src_clk", ce3_src_clk.c, "qcrypto.0"),
CLK_LOOKUP("dma_bam_pclk", dma_bam_p_clk.c, NULL),
- CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, "msm_serial_hsl.0"),
+ CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, "msm_serial_hsl.1"),
CLK_LOOKUP("iface_clk", gsbi2_p_clk.c, ""),
- CLK_LOOKUP("iface_clk", gsbi3_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi3_p_clk.c, "qup_i2c.3"),
CLK_LOOKUP("iface_clk", gsbi4_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "spi_qsd.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, ""),
- CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", tsif_p_clk.c, ""),
CLK_LOOKUP("iface_clk", usb_fs1_p_clk.c, ""),
CLK_LOOKUP("iface_clk", usb_hs1_p_clk.c, "msm_otg"),
@@ -4958,10 +4960,10 @@
CLK_LOOKUP("csiphy_timer_clk", csi0phy_timer_clk.c, ""),
CLK_LOOKUP("csiphy_timer_clk", csi1phy_timer_clk.c, ""),
CLK_LOOKUP("csiphy_timer_clk", csi2phy_timer_clk.c, ""),
- CLK_LOOKUP("dsi_byte_div_clk", dsi1_byte_clk.c, ""),
- CLK_LOOKUP("dsi_byte_div_clk", dsi2_byte_clk.c, ""),
- CLK_LOOKUP("dsi_esc_clk", dsi1_esc_clk.c, ""),
- CLK_LOOKUP("dsi_esc_clk", dsi2_esc_clk.c, ""),
+ CLK_LOOKUP("dsi_byte_div_clk", dsi1_byte_clk.c, NULL),
+ CLK_LOOKUP("dsi_byte_div_clk", dsi2_byte_clk.c, NULL),
+ CLK_LOOKUP("dsi_esc_clk", dsi1_esc_clk.c, NULL),
+ CLK_LOOKUP("dsi_esc_clk", dsi2_esc_clk.c, NULL),
CLK_DUMMY("rgb_tv_clk", RGB_TV_CLK, "", OFF),
CLK_DUMMY("npl_tv_clk", NPL_TV_CLK, "", OFF),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
@@ -4978,18 +4980,18 @@
CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, ""),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", jpegd_clk.c, ""),
- CLK_LOOKUP("mdp_clk", mdp_clk.c, ""),
+ CLK_LOOKUP("mdp_clk", mdp_clk.c, NULL),
CLK_LOOKUP("core_clk", mdp_clk.c, "footswitch-8x60.4"),
- CLK_LOOKUP("mdp_vsync_clk", mdp_vsync_clk.c, ""),
+ CLK_LOOKUP("mdp_vsync_clk", mdp_vsync_clk.c, NULL),
CLK_LOOKUP("vsync_clk", mdp_vsync_clk.c, "footswitch-8x60.4"),
- CLK_LOOKUP("lut_mdp", lut_mdp_clk.c, ""),
+ CLK_LOOKUP("lut_mdp", lut_mdp_clk.c, NULL),
CLK_LOOKUP("lut_clk", lut_mdp_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("core_clk", rot_clk.c, "msm_rotator.0"),
CLK_LOOKUP("core_clk", rot_clk.c, "footswitch-8x60.6"),
- CLK_DUMMY("tv_src_clk", TV_SRC_CLK, "", OFF),
+ CLK_DUMMY("tv_src_clk", TV_SRC_CLK, NULL, OFF),
CLK_LOOKUP("core_clk", vcodec_clk.c, "msm_vidc.0"),
CLK_LOOKUP("core_clk", vcodec_clk.c, "footswitch-8x60.7"),
- CLK_DUMMY("mdp_tv_clk", MDP_TV_CLK, "", OFF),
+ CLK_DUMMY("mdp_tv_clk", MDP_TV_CLK, NULL, OFF),
CLK_DUMMY("tv_clk", MDP_TV_CLK, "footswitch-8x60.4", OFF),
CLK_DUMMY("hdmi_clk", HDMI_TV_CLK, "", OFF),
CLK_LOOKUP("core_clk", hdmi_app_clk.c, ""),
@@ -5005,12 +5007,12 @@
CLK_LOOKUP("bus_a_clk", vcodec_axi_a_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("bus_b_clk", vcodec_axi_b_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("bus_clk", vpe_axi_clk.c, "footswitch-8x60.9"),
- CLK_LOOKUP("amp_pclk", amp_p_clk.c, ""),
+ CLK_LOOKUP("amp_pclk", amp_p_clk.c, NULL),
CLK_LOOKUP("csi_pclk", csi_p_clk.c, ""),
- CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, ""),
- CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, ""),
- CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, ""),
- CLK_LOOKUP("dsi_s_pclk", dsi2_s_p_clk.c, ""),
+ CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, NULL),
+ CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, NULL),
+ CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, NULL),
+ CLK_LOOKUP("dsi_s_pclk", dsi2_s_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, ""),
@@ -5019,7 +5021,7 @@
CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("iface_clk", jpegd_p_clk.c, ""),
CLK_LOOKUP("mem_iface_clk", imem_p_clk.c, "kgsl-3d0.0"),
- CLK_LOOKUP("mdp_pclk", mdp_p_clk.c, ""),
+ CLK_LOOKUP("mdp_pclk", mdp_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", mdp_p_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("iface_clk", smmu_p_clk.c, "msm_iommu"),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "msm_rotator.0"),
@@ -5030,6 +5032,7 @@
CLK_LOOKUP("iface_clk", vfe_p_clk.c, "footswitch-8x60.8"),
CLK_LOOKUP("vpe_pclk", vpe_p_clk.c, ""),
CLK_LOOKUP("iface_pclk", vpe_p_clk.c, "footswitch-8x60.9"),
+
CLK_LOOKUP("mi2s_bit_clk", mi2s_bit_clk.c, ""),
CLK_LOOKUP("mi2s_osr_clk", mi2s_osr_clk.c, ""),
CLK_LOOKUP("i2s_mic_bit_clk", codec_i2s_mic_bit_clk.c, ""),
@@ -5053,16 +5056,19 @@
CLK_LOOKUP("core_clk", vcodec_axi_a_clk.c, ""),
CLK_LOOKUP("core_clk", vcodec_axi_b_clk.c, ""),
CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, ""),
- CLK_DUMMY("dfab_dsps_clk", DFAB_DSPS_CLK, "", 0),
- CLK_DUMMY("core_clk", DFAB_USB_HS_CLK, "msm_otg", 0),
- CLK_DUMMY("core_clk", DFAB_USB_HS3_CLK, "msm_ehci_host.0", 0),
- CLK_DUMMY("core_clk", DFAB_USB_HS4_CLK, "msm_ehci_host.1", 0),
- CLK_DUMMY("bus_clk", DFAB_SDC1_CLK, "", 0),
- CLK_DUMMY("bus_clk", DFAB_SDC2_CLK, "", 0),
- CLK_DUMMY("bus_clk", DFAB_SDC3_CLK, "", 0),
- CLK_DUMMY("bus_clk", DFAB_SDC4_CLK, "", 0),
- CLK_DUMMY("dfab_clk", DFAB_CLK, "", 0),
- CLK_DUMMY("bus_clk", DFAB_SCM_CLK, "scm", 0),
+
+ CLK_LOOKUP("dfab_dsps_clk", dfab_dsps_clk.c, NULL),
+ CLK_LOOKUP("core_clk", dfab_usb_hs_clk.c, "msm_otg"),
+ CLK_LOOKUP("core_clk", dfab_usb_hs3_clk.c, "msm_ehci_host.0"),
+ CLK_LOOKUP("core_clk", dfab_usb_hs3_clk.c, "msm_ehci_host.1"),
+ CLK_LOOKUP("bus_clk", dfab_sdc1_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("bus_clk", dfab_sdc2_clk.c, "msm_sdcc.2"),
+ CLK_LOOKUP("bus_clk", dfab_sdc3_clk.c, "msm_sdcc.3"),
+ CLK_LOOKUP("bus_clk", dfab_sdc4_clk.c, "msm_sdcc.4"),
+ CLK_LOOKUP("dfab_clk", dfab_sps_clk.c, "msm_sps"),
+ CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
+ CLK_LOOKUP("bus_clk", dfab_scm_clk.c, "scm"),
+
CLK_LOOKUP("alt_core_clk", usb_hsic_xcvr_fs_clk.c, "msm_hsic_host"),
CLK_LOOKUP("phy_clk", usb_hsic_hsic_clk.c, "msm_hsic_host"),
CLK_LOOKUP("cal_clk", usb_hsic_hsio_cal_clk.c, "msm_hsic_host"),
@@ -5211,6 +5217,7 @@
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-006c"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0048"),
CLK_LOOKUP("cam_clk", cam2_clk.c, NULL),
+ CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0020"),
CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_csid.0"),
CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, "msm_csid.1"),
CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_csid.0"),
@@ -5243,7 +5250,7 @@
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk", ijpeg_axi_clk.c, "footswitch-8x60.3"),
- CLK_LOOKUP("mem_clk", imem_axi_clk.c, ""),
+ CLK_LOOKUP("imem_clk", imem_axi_clk.c, NULL),
CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, NULL),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", jpegd_clk.c, ""),
@@ -5534,134 +5541,38 @@
rmwreg(0, SATA_PHY_REF_CLK_CTL_REG, 0x1);
/*
- * TODO: Programming below PLLs is temporary and needs to be removed
- * after bootloaders program them.
+ * TODO: Programming below PLLs and prng_clk is temporary and
+ * needs to be removed after bootloaders program them.
*/
if (cpu_is_apq8064()) {
- u32 regval, is_pll_enabled;
+ u32 is_pll_enabled;
/* Program pxo_src_clk to source from PXO */
rmwreg(0x1, PXO_SRC_CLK_CTL_REG, 0x7);
- /* Check if PLL8 is active */
- is_pll_enabled = readl_relaxed(BB_PLL8_STATUS_REG) & BIT(16);
- if (!is_pll_enabled) {
- /* Ref clk = 27MHz and program pll8 to 384MHz */
- writel_relaxed(0xE, BB_PLL8_L_VAL_REG);
- writel_relaxed(0x2, BB_PLL8_M_VAL_REG);
- writel_relaxed(0x9, BB_PLL8_N_VAL_REG);
-
- regval = readl_relaxed(BB_PLL8_CONFIG_REG);
-
- /* Enable the main output and the MN accumulator */
- regval |= BIT(23) | BIT(22);
-
- /* Set pre-divider and post-divider values to 1 and 1 */
- regval &= ~BIT(19);
- regval &= ~BM(21, 20);
-
- writel_relaxed(regval, BB_PLL8_CONFIG_REG);
-
- /* Set VCO frequency */
- rmwreg(0x10000, BB_PLL8_CONFIG_REG, 0x30000);
-
- /* Enable AUX output */
- regval = readl_relaxed(BB_PLL8_TEST_CTL_REG);
- regval |= BIT(12);
- writel_relaxed(regval, BB_PLL8_TEST_CTL_REG);
-
- set_fsm_mode(BB_PLL8_MODE_REG);
-
- /* Enable PLL8 by voting from RPM */
- regval = readl_relaxed(BB_PLL_ENA_RPM_REG);
- regval |= BIT(8);
- writel_relaxed(regval, BB_PLL_ENA_RPM_REG);
- }
- /* Check if PLL3 is active */
- is_pll_enabled = readl_relaxed(GPLL1_STATUS_REG) & BIT(16);
- if (!is_pll_enabled) {
- /* Ref clk = 27MHz and program pll3 to 1200MHz */
- writel_relaxed(0x2C, GPLL1_L_VAL_REG);
- writel_relaxed(0x4, GPLL1_M_VAL_REG);
- writel_relaxed(0x9, GPLL1_N_VAL_REG);
-
- regval = readl_relaxed(GPLL1_CONFIG_REG);
-
- /* Set pre-divider and post-divider values to 1 and 1 */
- regval &= ~BIT(15);
- regval |= BIT(16);
-
- writel_relaxed(regval, GPLL1_CONFIG_REG);
-
- /* Set VCO frequency */
- rmwreg(0x180, GPLL1_CONFIG_REG, 0x180);
- }
/* Check if PLL14 is active */
is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
if (!is_pll_enabled) {
/* Ref clk = 27MHz and program pll14 to 480MHz */
- writel_relaxed(0x11, BB_PLL14_L_VAL_REG);
+ writel_relaxed(0x00031011, BB_PLL14_L_VAL_REG);
writel_relaxed(0x7, BB_PLL14_M_VAL_REG);
writel_relaxed(0x9, BB_PLL14_N_VAL_REG);
- regval = readl_relaxed(BB_PLL14_CONFIG_REG);
-
- /* Enable the main output and the MN accumulator */
- regval |= BIT(23) | BIT(22);
-
- /* Set pre-divider and post-divider values to 1 and 1 */
- regval &= ~BIT(19);
- regval &= ~BM(21, 20);
-
- writel_relaxed(regval, BB_PLL14_CONFIG_REG);
-
- /* Set VCO frequency */
- rmwreg(0x10000, BB_PLL14_CONFIG_REG, 0x30000);
+ /*
+ * Enable the main output and the MN accumulator
+ * Set pre-divider and post-divider values to 1 and 1
+ */
+ writel_relaxed(0x00C00000, BB_PLL14_CONFIG_REG);
set_fsm_mode(BB_PLL14_MODE_REG);
}
- /* Program PLL2 to 800MHz with ref clk = 27MHz */
- writel_relaxed(0x1D, MM_PLL1_L_VAL_REG);
- writel_relaxed(0x11, MM_PLL1_M_VAL_REG);
- writel_relaxed(0x1B, MM_PLL1_N_VAL_REG);
-
- regval = readl_relaxed(MM_PLL1_CONFIG_REG);
-
- /* Enable the main output and the MN accumulator */
- regval |= BIT(23) | BIT(22);
-
- /* Set pre-divider and post-divider values to 1 and 1 */
- regval &= ~BIT(19);
- regval &= ~BM(21, 20);
-
- writel_relaxed(regval, MM_PLL1_CONFIG_REG);
-
- /* Set VCO frequency */
- rmwreg(0x20000, MM_PLL1_CONFIG_REG, 0x30000);
/* Program PLL15 to 975MHz with ref clk = 27MHz */
- writel_relaxed(0x24, MM_PLL3_L_VAL_REG);
- writel_relaxed(0x1, MM_PLL3_M_VAL_REG);
- writel_relaxed(0x9, MM_PLL3_N_VAL_REG);
+ writel_relaxed(0x31024, MM_PLL3_L_VAL_REG);
+ writel_relaxed(0x1, MM_PLL3_M_VAL_REG);
+ writel_relaxed(0x9, MM_PLL3_N_VAL_REG);
- regval = readl_relaxed(MM_PLL3_CONFIG_REG);
-
- /* Enable the main output and the MN accumulator */
- regval |= BIT(23) | BIT(22);
-
- /* Set pre-divider and post-divider values to 1 and 1 */
- regval &= ~BIT(19);
- regval &= ~BM(21, 20);
-
- writel_relaxed(regval, MM_PLL3_CONFIG_REG);
-
- /* Set VCO frequency */
- rmwreg(0x20000, MM_PLL3_CONFIG_REG, 0x30000);
-
- /* Enable AUX output */
- regval = readl_relaxed(MM_PLL3_TEST_CTL_REG);
- regval |= BIT(12);
- writel_relaxed(regval, MM_PLL3_TEST_CTL_REG);
+ writel_relaxed(0xC20000, MM_PLL3_CONFIG_REG);
/* Check if PLL4 is active */
is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
@@ -5671,30 +5582,27 @@
writel_relaxed(0x27A, LCC_PLL0_M_VAL_REG);
writel_relaxed(0x465, LCC_PLL0_N_VAL_REG);
- regval = readl_relaxed(LCC_PLL0_CONFIG_REG);
-
- /* Enable the main output and the MN accumulator */
- regval |= BIT(23) | BIT(22);
-
- /* Set pre-divider and post-divider values to 1 and 1 */
- regval &= ~BIT(19);
- regval &= ~BM(21, 20);
-
- /* Set VCO frequency */
- regval &= ~BM(17, 16);
- writel_relaxed(regval, LCC_PLL0_CONFIG_REG);
+ writel_relaxed(0xC00000, LCC_PLL0_CONFIG_REG);
set_fsm_mode(LCC_PLL0_MODE_REG);
}
/* Enable PLL4 source on the LPASS Primary PLL Mux */
writel_relaxed(0x1, LCC_PRI_PLL_CLK_CTL_REG);
+
+ /* Program prng_clk to 64MHz if it isn't configured */
+ if (!readl_relaxed(PRNG_CLK_NS_REG))
+ writel_relaxed(0x2B, PRNG_CLK_NS_REG);
}
}
/* Local clock driver initialization. */
static void __init msm8960_clock_init(void)
{
+ /* Copy gfx2d's frequency table because it's modified by both clocks */
+ gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
+ sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
+ GFP_KERNEL);
if (cpu_is_msm8960()) {
rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 043cdbc..e53d441 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3900,6 +3900,11 @@
}
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ /* Copy gfx2d's frequency table because it's modified by both clocks */
+ gfx2d1_clk.freq_tbl = kmemdup(clk_tbl_gfx2d,
+ sizeof(struct clk_freq_tbl) * ARRAY_SIZE(clk_tbl_gfx2d),
+ GFP_KERNEL);
+
/* Initialize clock registers. */
reg_init();
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 98d9cb2..ac68d7a 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -384,6 +384,10 @@
.enable = rcg_clk_enable,
.disable = rcg_clk_disable,
.auto_off = rcg_clk_disable,
+ .enable_hwcg = rcg_clk_enable_hwcg,
+ .disable_hwcg = rcg_clk_disable_hwcg,
+ .in_hwcg_mode = rcg_clk_in_hwcg_mode,
+ .handoff = rcg_clk_handoff,
.set_rate = rcg_clk_set_rate,
.get_rate = rcg_clk_get_rate,
.list_rate = rcg_clk_list_rate,
@@ -398,6 +402,10 @@
.enable = branch_clk_enable,
.disable = branch_clk_disable,
.auto_off = branch_clk_disable,
+ .enable_hwcg = branch_clk_enable_hwcg,
+ .disable_hwcg = branch_clk_disable_hwcg,
+ .in_hwcg_mode = branch_clk_in_hwcg_mode,
+ .handoff = branch_clk_handoff,
.is_enabled = branch_clk_is_enabled,
.reset = branch_clk_reset,
.is_local = local_clk_is_local,
@@ -595,6 +603,8 @@
.b = {
.ctl_reg = PMEM_ACLK_CTL_REG,
.en_mask = BIT(4),
+ .hwcg_reg = PMEM_ACLK_CTL_REG,
+ .hwcg_mask = BIT(6),
.halt_reg = CLK_HALT_DFAB_STATE_REG,
.halt_bit = 20,
},
@@ -846,6 +856,8 @@
.b = {
.ctl_reg = CE1_CORE_CLK_CTL_REG,
.en_mask = BIT(4),
+ .hwcg_reg = CE1_CORE_CLK_CTL_REG,
+ .hwcg_mask = BIT(6),
.halt_reg = CLK_HALT_CFPB_STATEC_REG,
.halt_bit = 27,
},
@@ -957,6 +969,8 @@
.b = {
.ctl_reg = USB_HS1_HCLK_CTL_REG,
.en_mask = BIT(4),
+ .hwcg_reg = USB_HS1_HCLK_CTL_REG,
+ .hwcg_mask = BIT(6),
.halt_reg = CLK_HALT_DFAB_STATE_REG,
.halt_bit = 1,
},
@@ -971,6 +985,8 @@
.b = {
.ctl_reg = USB_HSIC_HCLK_CTL_REG,
.en_mask = BIT(4),
+ .hwcg_reg = USB_HSIC_HCLK_CTL_REG,
+ .hwcg_mask = BIT(6),
.halt_reg = CLK_HALT_DFAB_STATE_REG,
.halt_bit = 3,
},
@@ -985,6 +1001,8 @@
.b = {
.ctl_reg = SDCn_HCLK_CTL_REG(1),
.en_mask = BIT(4),
+ .hwcg_reg = SDCn_HCLK_CTL_REG(1),
+ .hwcg_mask = BIT(6),
.halt_reg = CLK_HALT_DFAB_STATE_REG,
.halt_bit = 11,
},
@@ -999,6 +1017,8 @@
.b = {
.ctl_reg = SDCn_HCLK_CTL_REG(2),
.en_mask = BIT(4),
+ .hwcg_reg = SDCn_HCLK_CTL_REG(2),
+ .hwcg_mask = BIT(6),
.halt_reg = CLK_HALT_DFAB_STATE_REG,
.halt_bit = 10,
},
@@ -1807,22 +1827,13 @@
regval = readl_relaxed(LCC_PRI_PLL_CLK_CTL_REG);
writel_relaxed(regval | BIT(0), LCC_PRI_PLL_CLK_CTL_REG);
- /* Disable hardware clock gating on certain clocks */
- regval = readl_relaxed(USB_HSIC_HCLK_CTL_REG);
+ /*
+ * Disable hardware clock gating for pmem_clk. Leaving it enabled
+ * results in the clock staying on.
+ */
+ regval = readl_relaxed(PMEM_ACLK_CTL_REG);
regval &= ~BIT(6);
- writel_relaxed(regval, USB_HSIC_HCLK_CTL_REG);
-
- regval = readl_relaxed(CE1_CORE_CLK_CTL_REG);
- regval &= ~BIT(6);
- writel_relaxed(regval, CE1_CORE_CLK_CTL_REG);
-
- regval = readl_relaxed(USB_HS1_HCLK_CTL_REG);
- regval &= ~BIT(6);
- writel_relaxed(regval, USB_HS1_HCLK_CTL_REG);
-
- regval = readl_relaxed(DMA_BAM_HCLK_CTL);
- regval &= ~BIT(6);
- writel_relaxed(regval, DMA_BAM_HCLK_CTL);
+ writel_relaxed(regval, PMEM_ACLK_CTL_REG);
}
/* Local clock driver initialization. */
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 8ea344b..d312f24 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -106,7 +106,6 @@
const uint32_t ns_val;
const uint32_t ctl_val;
uint32_t mnd_en_mask;
- const unsigned sys_vdd;
void *const extra_freq_data;
};
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 81d01c2..56778e2 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -173,6 +173,14 @@
struct cpufreq_work_struct *cpu_work = NULL;
#endif
+ /*
+ * In 8625 both cpu core's frequency can not
+ * be changed independently. Each cpu is bound to
+ * same frequency. Hence set the cpumask to all cpu.
+ */
+ if (cpu_is_msm8625())
+ cpumask_setall(policy->cpus);
+
table = cpufreq_frequency_get_table(policy->cpu);
if (table == NULL)
return -ENODEV;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index faa9498..9328143 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -28,6 +28,7 @@
#include <mach/msm_bus_board.h>
#include <mach/rpm.h>
#include <mach/mdm2.h>
+#include <linux/ion.h>
#include "clock.h"
#include "devices.h"
#include "msm_watchdog.h"
@@ -46,6 +47,7 @@
/* GSBI UART devices */
#define MSM_UART1DM_PHYS (MSM_GSBI1_PHYS + 0x10000)
#define MSM_UART3DM_PHYS (MSM_GSBI3_PHYS + 0x40000)
+#define MSM_UART7DM_PHYS (MSM_GSBI7_PHYS + 0x40000)
/* GSBI QUP devices */
#define MSM_GSBI3_QUP_PHYS (MSM_GSBI3_PHYS + 0x80000)
@@ -68,6 +70,7 @@
.pet_time = 10000,
.bark_time = 11000,
.has_secure = true,
+ .needs_expired_enable = true,
};
struct platform_device msm8064_device_watchdog = {
@@ -127,7 +130,7 @@
struct platform_device apq8064_device_uart_gsbi1 = {
.name = "msm_serial_hsl",
- .id = 0,
+ .id = 1,
.num_resources = ARRAY_SIZE(resources_uart_gsbi1),
.resource = resources_uart_gsbi1,
};
@@ -159,6 +162,46 @@
.resource = resources_uart_gsbi3,
};
+static struct resource resources_qup_i2c_gsbi3[] = {
+ {
+ .name = "gsbi_qup_i2c_addr",
+ .start = MSM_GSBI3_PHYS,
+ .end = MSM_GSBI3_PHYS + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "qup_phys_addr",
+ .start = MSM_GSBI3_QUP_PHYS,
+ .end = MSM_GSBI3_QUP_PHYS + MSM_QUP_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "qup_err_intr",
+ .start = GSBI3_QUP_IRQ,
+ .end = GSBI3_QUP_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "i2c_clk",
+ .start = 9,
+ .end = 9,
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .name = "i2c_sda",
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+struct platform_device apq8064_device_qup_i2c_gsbi3 = {
+ .name = "qup_i2c",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(resources_qup_i2c_gsbi3),
+ .resource = resources_qup_i2c_gsbi3,
+};
+
static struct resource resources_qup_i2c_gsbi4[] = {
{
.name = "gsbi_qup_i2c_addr",
@@ -215,6 +258,33 @@
.resource = resources_qup_spi_gsbi5,
};
+static struct resource resources_uart_gsbi7[] = {
+ {
+ .start = GSBI7_UARTDM_IRQ,
+ .end = GSBI7_UARTDM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_UART7DM_PHYS,
+ .end = MSM_UART7DM_PHYS + PAGE_SIZE - 1,
+ .name = "uartdm_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_GSBI7_PHYS,
+ .end = MSM_GSBI7_PHYS + PAGE_SIZE - 1,
+ .name = "gsbi_resource",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device apq8064_device_uart_gsbi7 = {
+ .name = "msm_serial_hsl",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(resources_uart_gsbi7),
+ .resource = resources_uart_gsbi7,
+};
+
struct platform_device apq_pcm = {
.name = "msm-pcm-dsp",
.id = -1,
@@ -353,6 +423,7 @@
#define LPASS_SLIMBUS_PHYS 0x28080000
#define LPASS_SLIMBUS_BAM_PHYS 0x28084000
+#define LPASS_SLIMBUS_SLEW (MSM8960_TLMM_PHYS + 0x207C)
/* Board info for the slimbus slave device */
static struct resource slimbus_res[] = {
{
@@ -368,6 +439,12 @@
.name = "slimbus_bam_physical",
},
{
+ .start = LPASS_SLIMBUS_SLEW,
+ .end = LPASS_SLIMBUS_SLEW + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "slimbus_slew_reg",
+ },
+ {
.start = SLIMBUS0_CORE_EE1_IRQ,
.end = SLIMBUS0_CORE_EE1_IRQ,
.flags = IORESOURCE_IRQ,
@@ -514,6 +591,270 @@
},
};
+/* MSM Video core device */
+#ifdef CONFIG_MSM_BUS_SCALING
+static struct msm_bus_vectors vidc_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+static struct msm_bus_vectors vidc_venc_vga_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 54525952,
+ .ib = 436207616,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 72351744,
+ .ib = 289406976,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 1000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 1000000,
+ },
+};
+static struct msm_bus_vectors vidc_vdec_vga_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 40894464,
+ .ib = 327155712,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 48234496,
+ .ib = 192937984,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 2000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 2000000,
+ },
+};
+static struct msm_bus_vectors vidc_venc_720p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 163577856,
+ .ib = 1308622848,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 219152384,
+ .ib = 876609536,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 3500000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 3500000,
+ },
+};
+static struct msm_bus_vectors vidc_vdec_720p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 121634816,
+ .ib = 973078528,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 155189248,
+ .ib = 620756992,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 7000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 7000000,
+ },
+};
+static struct msm_bus_vectors vidc_venc_1080p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 372244480,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 501219328,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 5000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 5000000,
+ },
+};
+static struct msm_bus_vectors vidc_vdec_1080p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 222298112,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 330301440,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 700000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 10000000,
+ },
+};
+
+static struct msm_bus_paths vidc_bus_client_config[] = {
+ {
+ ARRAY_SIZE(vidc_init_vectors),
+ vidc_init_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_venc_vga_vectors),
+ vidc_venc_vga_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_vdec_vga_vectors),
+ vidc_vdec_vga_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_venc_720p_vectors),
+ vidc_venc_720p_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_vdec_720p_vectors),
+ vidc_vdec_720p_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_venc_1080p_vectors),
+ vidc_venc_1080p_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_vdec_1080p_vectors),
+ vidc_vdec_1080p_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata vidc_bus_client_data = {
+ vidc_bus_client_config,
+ ARRAY_SIZE(vidc_bus_client_config),
+ .name = "vidc",
+};
+#endif
+
+
+#define APQ8064_VIDC_BASE_PHYS 0x04400000
+#define APQ8064_VIDC_BASE_SIZE 0x00100000
+
+static struct resource apq8064_device_vidc_resources[] = {
+ {
+ .start = APQ8064_VIDC_BASE_PHYS,
+ .end = APQ8064_VIDC_BASE_PHYS + APQ8064_VIDC_BASE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = VCODEC_IRQ,
+ .end = VCODEC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct msm_vidc_platform_data apq8064_vidc_platform_data = {
+#ifdef CONFIG_MSM_BUS_SCALING
+ .vidc_bus_client_pdata = &vidc_bus_client_data,
+#endif
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ .memtype = ION_CP_MM_HEAP_ID,
+ .enable_ion = 1,
+#else
+ .memtype = MEMTYPE_EBI1,
+ .enable_ion = 0,
+#endif
+ .disable_dmx = 0,
+ .disable_fullhd = 0,
+};
+
+struct platform_device apq8064_msm_device_vidc = {
+ .name = "msm_vidc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(apq8064_device_vidc_resources),
+ .resource = apq8064_device_vidc_resources,
+ .dev = {
+ .platform_data = &apq8064_vidc_platform_data,
+ },
+};
#define MSM_SDC1_BASE 0x12400000
#define MSM_SDC1_DML_BASE (MSM_SDC1_BASE + 0x800)
#define MSM_SDC1_BAM_BASE (MSM_SDC1_BASE + 0x2000)
@@ -856,7 +1197,7 @@
CLK_DUMMY("core_clk", GSBI1_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI2_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI3_UART_CLK,
- "msm_serial_hsl.0", OFF),
+ NULL, OFF),
CLK_DUMMY("core_clk", GSBI4_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI5_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI6_UART_CLK, NULL, OFF),
@@ -868,7 +1209,7 @@
CLK_DUMMY("core_clk", GSBI12_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI1_QUP_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI2_QUP_CLK, NULL, OFF),
- CLK_DUMMY("core_clk", GSBI3_QUP_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", GSBI3_QUP_CLK, "qup_i2c.3", OFF),
CLK_DUMMY("core_clk", GSBI4_QUP_CLK, "qup_i2c.4", OFF),
CLK_DUMMY("core_clk", GSBI5_QUP_CLK, "spi_qsd.0", OFF),
CLK_DUMMY("core_clk", GSBI6_QUP_CLK, NULL, OFF),
@@ -900,7 +1241,7 @@
CLK_DUMMY("ref_clk", SATA_PHY_REF_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", GSBI1_P_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", GSBI2_P_CLK, NULL, OFF),
- CLK_DUMMY("iface_clk", GSBI3_P_CLK, "msm_serial_hsl.0", OFF),
+ CLK_DUMMY("iface_clk", GSBI3_P_CLK, "qup_i2c.3", OFF),
CLK_DUMMY("iface_clk", GSBI4_P_CLK, "qup_i2c.4", OFF),
CLK_DUMMY("iface_clk", GSBI5_P_CLK, "spi_qsd.0", OFF),
CLK_DUMMY("iface_clk", GSBI6_P_CLK, NULL, OFF),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 872d9d4..4525bab 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1389,6 +1389,11 @@
.id = -1,
};
+struct platform_device msm_multi_ch_pcm = {
+ .name = "msm-multi-ch-pcm-dsp",
+ .id = -1,
+};
+
struct platform_device msm_pcm_routing = {
.name = "msm-pcm-routing",
.id = -1,
@@ -1405,7 +1410,7 @@
};
struct platform_device msm_cpudai_hdmi_rx = {
- .name = "msm-dai-q6",
+ .name = "msm-dai-q6-hdmi",
.id = 8,
};
@@ -1658,7 +1663,7 @@
};
#endif
-static struct platform_device msm_lvds_device = {
+struct platform_device msm_lvds_device = {
.name = "lvds",
.id = 0,
};
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 1f2256f..3944a93 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1116,12 +1116,6 @@
msm_mpm_irq_extn_init(data);
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
(void *)MSM_QGIC_CPU_BASE);
-
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
- mb();
}
struct platform_device msm_bus_9615_sys_fabric = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index f3a95a6..31eee43 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -866,6 +866,24 @@
.resource = gsbi0_msm8625_qup_resources,
};
+static struct resource msm8625_gpio_resources[] = {
+ {
+ .start = MSM8625_INT_GPIO_GROUP1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM8625_INT_GPIO_GROUP2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device msm8625_device_gpio = {
+ .name = "msmgpio",
+ .id = -1,
+ .resource = msm8625_gpio_resources,
+ .num_resources = ARRAY_SIZE(msm8625_gpio_resources),
+};
+
static struct clk_lookup msm_clock_8625_dummy[] = {
CLK_DUMMY("core_clk", adm_clk.c, "msm_dmov", 0),
CLK_DUMMY("adsp_clk", adsp_clk.c, NULL, 0),
@@ -987,13 +1005,6 @@
{
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
(void *)MSM_QGIC_CPU_BASE);
-
- /* Edge trigger PPIs
- */
- writel_relaxed(0x555555F5, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
- mb();
}
void __init msm8625_map_io(void)
@@ -1007,7 +1018,10 @@
static int msm7627a_init_gpio(void)
{
- platform_device_register(&msm_device_gpio);
+ if (cpu_is_msm8625())
+ platform_device_register(&msm8625_device_gpio);
+ else
+ platform_device_register(&msm_device_gpio);
return 0;
}
postcore_initcall(msm7627a_init_gpio);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index db656f3..fc732da 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -581,9 +581,67 @@
},
};
+static struct resource smd_resource[] = {
+ {
+ .name = "a9_m2a_0",
+ .start = INT_A9_M2A_0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "a9_m2a_5",
+ .start = INT_A9_M2A_5,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "adsp_a11_smsm",
+ .start = INT_ADSP_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+ {
+ .irq_config_id = SMD_MODEM,
+ .subsys_name = "modem",
+ .edge = SMD_APPS_MODEM,
+
+ .smd_int.irq_name = "a9_m2a_0",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+
+ .smd_int.out_bit_pos = 1 << 0,
+ .smd_int.out_base = (void __iomem *)MSM_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "a9_m2a_5",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_dev",
+ .smsm_int.dev_id = 0,
+
+ .smsm_int.out_bit_pos = 1 << 5,
+ .smsm_int.out_base = (void __iomem *)MSM_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+
+ }
+};
+
+static struct smd_platform smd_platform_data = {
+ .num_ss_configs = ARRAY_SIZE(smd_config_list),
+ .smd_ss_configs = smd_config_list,
+};
+
struct platform_device msm_device_smd = {
.name = "msm_smd",
.id = -1,
+ .resource = smd_resource,
+ .num_resources = ARRAY_SIZE(smd_resource),
+ .dev = {
+ .platform_data = &smd_platform_data,
+ }
+
};
static struct resource msm_dmov_resource[] = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index a433a89..4670ce8 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -179,9 +179,6 @@
msm_mpm_irq_extn_init(data);
gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, (void *)MSM_QGIC_CPU_BASE);
-
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
}
#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
diff --git a/arch/arm/mach-msm/devices-msm8x60.h b/arch/arm/mach-msm/devices-msm8x60.h
index a2f6a1f..9bfaeee 100644
--- a/arch/arm/mach-msm/devices-msm8x60.h
+++ b/arch/arm/mach-msm/devices-msm8x60.h
@@ -56,6 +56,7 @@
extern struct platform_device msm_device_smd;
extern struct platform_device msm_device_gpio;
extern struct platform_device msm_device_vidc;
+extern struct platform_device apq8064_msm_device_vidc;
extern struct platform_device msm_charm_modem;
extern struct platform_device msm_device_tz_log;
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 9469de8..c4f57ab 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -69,6 +69,8 @@
extern struct platform_device apq8064_device_uart_gsbi1;
extern struct platform_device apq8064_device_uart_gsbi3;
+extern struct platform_device apq8064_device_uart_gsbi7;
+extern struct platform_device apq8064_device_qup_i2c_gsbi3;
extern struct platform_device apq8064_device_qup_i2c_gsbi4;
extern struct platform_device apq8064_device_qup_spi_gsbi5;
extern struct platform_device apq8064_slim_ctrl;
@@ -162,6 +164,7 @@
extern struct platform_device msm_device_vidc_720p;
extern struct platform_device msm_pcm;
+extern struct platform_device msm_multi_ch_pcm;
extern struct platform_device msm_pcm_routing;
extern struct platform_device msm_cpudai0;
extern struct platform_device msm_cpudai1;
@@ -234,6 +237,7 @@
extern struct platform_device msm_kgsl_2d1;
extern struct platform_device msm_mipi_dsi1_device;
+extern struct platform_device msm_lvds_device;
extern struct clk_lookup msm_clocks_fsm9xxx[];
extern unsigned msm_num_clocks_fsm9xxx;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 296c111..5c10463 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -623,7 +623,7 @@
init_data = pdev->dev.platform_data;
if (pdev->id == FS_MDP) {
- if (cpu_is_msm8960() || cpu_is_msm8930())
+ if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064())
fs->clk_data = mdp_8960_clks;
else if (cpu_is_msm8x60())
fs->clk_data = mdp_8660_clks;
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 631d5200..c274899 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -106,12 +106,6 @@
sub r1, r1, r0
bl v7_flush_kern_dcache_area
- mrc p15, 0, r4, c1, c0, 0 /* read current CR */
- bic r0, r4, #(1 << 2) /* clear dcache bit */
- bic r0, r0, #(1 << 12) /* clear icache bit */
- mcr p15, 0, r0, c1, c0, 0 /* disable d/i cache */
-
- dsb
#ifdef CONFIG_ARCH_MSM_KRAIT
ldr r0, =SCM_SVC_BOOT
ldr r1, =SCM_CMD_TERMINATE_PC
@@ -119,10 +113,18 @@
ldr r2, [r2]
bl scm_call_atomic1
#else
+ mrc p15, 0, r4, c1, c0, 0 /* read current CR */
+ bic r0, r4, #(1 << 2) /* clear dcache bit */
+ bic r0, r0, #(1 << 12) /* clear icache bit */
+ mcr p15, 0, r0, c1, c0, 0 /* disable d/i cache */
+ dsb
+
wfi
-#endif
+
mcr p15, 0, r4, c1, c0, 0 /* restore d/i cache */
isb
+#endif
+
#if defined(CONFIG_MSM_FIQ_SUPPORT)
cpsie f
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 6eceea7..ba9fc70 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -399,6 +399,10 @@
char dlane_swap;
};
+struct lvds_panel_platform_data {
+ int *gpio;
+};
+
struct msm_fb_platform_data {
int (*detect_client)(const char *name);
int mddi_prescan;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index bb33289..530d2c1 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -213,6 +213,7 @@
#define CSI_DECODE_6BIT 0
#define CSI_DECODE_8BIT 1
#define CSI_DECODE_10BIT 2
+#define CSI_DECODE_DPCM_10_8_10 5
struct msm_vfe_phy_info {
uint32_t sbuf_phy;
@@ -576,6 +577,7 @@
CAMIO_CSI0_PHY_CLK,
CAMIO_CSI1_PHY_CLK,
CAMIO_CSIPHY_TIMER_SRC_CLK,
+ CAMIO_IMEM_CLK,
CAMIO_MAX_CLK
};
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index 1a87d9c..fd61c98 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -205,7 +205,7 @@
MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
MSM_BUS_MASTER_VIDEO_ENC,
MSM_BUS_MASTER_VIDEO_DEC,
- MSM_BUS_MASTER_LAST = MSM_BUS_MMSS_MASTER_UNUSED_2,
+ MSM_BUS_MASTER_LAST = MSM_BUS_MASTER_VIDEO_DEC,
MSM_BUS_SYSTEM_FPB_MASTER_SYSTEM =
MSM_BUS_SYSTEM_MASTER_SYSTEM_FPB,
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 562a305..57e794f 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,15 @@
#ifndef __MSM_HDMI_AUDIO_H
#define __MSM_HDMI_AUDIO_H
+/* Supported HDMI Audio channels */
+#define MSM_HDMI_AUDIO_CHANNEL_2 0
+#define MSM_HDMI_AUDIO_CHANNEL_4 1
+#define MSM_HDMI_AUDIO_CHANNEL_6 2
+#define MSM_HDMI_AUDIO_CHANNEL_8 3
+
+#define TRUE 1
+#define FALSE 0
+
enum hdmi_supported_sample_rates {
HDMI_SAMPLE_RATE_32KHZ,
HDMI_SAMPLE_RATE_44_1KHZ,
@@ -27,5 +36,7 @@
int hdmi_audio_packet_enable(bool on);
void hdmi_msm_audio_sample_rate_reset(int rate);
int hdmi_msm_audio_get_sample_rate(void);
+int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
+ u32 channel_allocation, u32 level_shift, bool down_mix);
#endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
index 88bc3c6..4c26d08 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
@@ -44,9 +44,6 @@
#define MSM7XXX_TMR_PHYS MSM7XXX_CSR_PHYS
#define MSM7XXX_TMR_SIZE SZ_4K
-#define MSM7XXX_TMR0_PHYS 0xC0800000
-#define MSM7XXX_TMR0_SIZE SZ_4K
-
#define MSM7XXX_GPIO1_PHYS 0xA9200000
#define MSM7XXX_GPIO1_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index ca8daaa..d53910d 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,9 +47,7 @@
#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
- defined(CONFIG_ARCH_MSMCOPPER) || defined(CONFIG_ARCH_MSM7X27) || \
- defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7X25) || \
- defined(CONFIG_ARCH_MSM8625)
+ defined(CONFIG_ARCH_MSMCOPPER)
/* Unified iomap */
@@ -82,21 +80,8 @@
#define MSM_APCS_GLB_BASE IOMEM(0xFA702000) /* 4K */
#define MSM_SAW2_BASE IOMEM(0xFA703000) /* 4k */
#define MSM_SAW3_BASE IOMEM(0xFA704000) /* 4k */
-#define MSM_VIC_BASE IOMEM(0xFA705000) /* 4K */
-#define MSM_CSR_BASE MSM_TMR_BASE /* 4K */
-#define MSM_GPIO1_BASE IOMEM(0xFA706000) /* 4K */
-#define MSM_GPIO2_BASE IOMEM(0xFA707000) /* 4K */
-#define MSM_SCU_BASE IOMEM(0xFA708000) /* 4K */
-#define MSM_SPM0_BASE IOMEM(0xFA709000) /* 4K */
-#define MSM_SPM1_BASE IOMEM(0xFA70A000) /* 4K */
-#define MSM_CFG_CTL_BASE IOMEM(0xFA70B000) /* 4K */
-#define MSM_MDC_BASE IOMEM(0xFA70C000) /* 4K */
-#define MSM_AD5_BASE IOMEM(0xFA70D000) /* 4K */
-
-#define MSM_STRONGLY_ORDERED_PAGE 0xFA0F0000
-
-#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27)
+#if defined(CONFIG_ARCH_MSM9615)
#define MSM_SHARED_RAM_SIZE SZ_1M
#else
#define MSM_SHARED_RAM_SIZE SZ_2M
@@ -107,8 +92,6 @@
#include "msm_iomap-8064.h"
#include "msm_iomap-9615.h"
#include "msm_iomap-copper.h"
-#include "msm_iomap-7xxx.h"
-#include "msm_iomap-8625.h"
#else
/* Legacy single-target iomap */
@@ -122,7 +105,29 @@
#elif defined(CONFIG_ARCH_FSM9XXX)
#include "msm_iomap-fsm9xxx.h"
#else
-#error "Target compiling without iomap"
+#define MSM_VIC_BASE IOMEM(0xFA000000) /* 4K */
+#define MSM_CSR_BASE IOMEM(0xFA001000) /* 4K */
+#define MSM_TMR_BASE MSM_CSR_BASE /* 4K */
+#define MSM_TMR0_BASE IOMEM(0xFA002000) /* 4K */
+#define MSM_GPIO1_BASE IOMEM(0xFA003000) /* 4K */
+#define MSM_GPIO2_BASE IOMEM(0xFA004000) /* 4K */
+#define MSM_CLK_CTL_BASE IOMEM(0xFA005000) /* 4K */
+#define MSM_L2CC_BASE IOMEM(0xFA006000) /* 4K */
+#define MSM_QGIC_DIST_BASE IOMEM(0xFA007000) /* 4K */
+#define MSM_QGIC_CPU_BASE IOMEM(0xFA008000) /* 4K */
+#define MSM_SCU_BASE IOMEM(0xFA009000) /* 4K */
+#define MSM_SPM0_BASE IOMEM(0xFA00A000) /* 4K */
+#define MSM_SPM1_BASE IOMEM(0xFA00B000) /* 4K */
+#define MSM_CFG_CTL_BASE IOMEM(0xFA00C000) /* 4K */
+#define MSM_SHARED_RAM_BASE IOMEM(0xFA100000) /* 4K */
+#define MSM_MDC_BASE IOMEM(0xFA200000) /* 4K */
+#define MSM_AD5_BASE IOMEM(0xFA300000) /* 4K */
+#define MSM_STRONGLY_ORDERED_PAGE 0xFA0F0000
+#define MSM8625_SECONDARY_PHYS 0x0FE00000
+#define MSM_SHARED_RAM_SIZE SZ_1M
+
+#include "msm_iomap-7xxx.h"
+#include "msm_iomap-8625.h"
#endif
#if defined(CONFIG_DEBUG_MSM_UART1)
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index a24e892..ac45cbd 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -17,6 +17,7 @@
LOGK_NONE = 0,
LOGK_READL,
LOGK_WRITEL,
+ LOGK_LOGBUF,
LOGK_OTHER,
};
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index af47425..4be6d9ea 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-msm/msm_smd.h
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -18,6 +18,9 @@
#ifndef __ASM_ARCH_MSM_SMD_H
#define __ASM_ARCH_MSM_SMD_H
+#include <linux/io.h>
+#include <mach/msm_smsm.h>
+
typedef struct smd_channel smd_channel_t;
#define SMD_MAX_CH_NAME_LEN 20 /* includes null char at end */
@@ -28,6 +31,24 @@
#define SMD_EVENT_STATUS 4
#define SMD_EVENT_REOPEN_READY 5
+/*
+ * SMD Processor ID's.
+ *
+ * For all processors that have both SMSM and SMD clients,
+ * the SMSM Processor ID and the SMD Processor ID will
+ * be the same. In cases where a processor only supports
+ * SMD, the entry will only exist in this enum.
+ */
+enum {
+ SMD_APPS = SMSM_APPS,
+ SMD_MODEM = SMSM_MODEM,
+ SMD_Q6 = SMSM_Q6,
+ SMD_WCNSS = SMSM_WCNSS,
+ SMD_DSPS = SMSM_DSPS,
+ SMD_MODEM_Q6_FW,
+ NUM_SMD_SUBSYSTEMS,
+};
+
enum {
SMD_APPS_MODEM = 0,
SMD_APPS_QDSP,
@@ -49,6 +70,59 @@
};
+/*
+ * SMD IRQ Configuration
+ *
+ * Used to initialize IRQ configurations from platform data
+ *
+ * @irq_name: irq_name to query platform data
+ * @irq_id: initialized to -1 in platform data, stores actual irq id on
+ * successful registration
+ * @out_base: if not null then settings used for outgoing interrupt
+ * initialied from platform data
+ */
+
+struct smd_irq_config {
+ /* incoming interrupt config */
+ const char *irq_name;
+ unsigned long flags;
+ int irq_id;
+ const char *device_name;
+ const void *dev_id;
+
+ /* outgoing interrupt config */
+ uint32_t out_bit_pos;
+ void __iomem *out_base;
+ uint32_t out_offset;
+};
+
+/*
+ * SMD subsystem configurations
+ *
+ * SMD subsystems configurations for platform data. This contains the
+ * M2A and A2M interrupt configurations for both SMD and SMSM per
+ * subsystem.
+ *
+ * @subsys_name: name of subsystem passed to PIL
+ * @irq_config_id: unique id for each subsystem
+ * @edge: maps to actual remote subsystem edge
+ *
+ */
+struct smd_subsystem_config {
+ unsigned irq_config_id;
+ const char *subsys_name;
+ int edge;
+
+ struct smd_irq_config smd_int;
+ struct smd_irq_config smsm_int;
+
+};
+
+struct smd_platform {
+ uint32_t num_ss_configs;
+ struct smd_subsystem_config *smd_ss_configs;
+};
+
#ifdef CONFIG_MSM_SMD
/* warning: notify() may be called before open returns */
int smd_open(const char *name, smd_channel_t **ch, void *priv,
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index 0d113ac..f8f4c87 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -163,6 +163,10 @@
*
* Consumers can vote to disable a regulator with this function by passing
* min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well. For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
*/
int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
int max_uV, int sleep_also);
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 600a2e91..c856455 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -43,123 +43,10 @@
char *name;
int domain;
} msm_iommu_ctx_names[] = {
- /* Camera */
- {
- .name = "vpe_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_vg1",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_vg2",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_rgb1",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_rgb2",
- .domain = GLOBAL_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_mm1",
- .domain = GLOBAL_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_b_mm2",
- .domain = GLOBAL_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_stream",
- .domain = GLOBAL_DOMAIN,
- },
-};
-
-static struct mem_pool global_pools[] = {
- [VIDEO_FIRMWARE_POOL] =
- /* Low addresses, intended for video firmware */
- {
- .paddr = SZ_128K,
- .size = SZ_16M - SZ_128K,
- },
- [LOW_256MB_POOL] =
- /*
- * Video can only access first 256MB of memory
- * dedicated pool for such allocations
- */
- {
- .paddr = SZ_16M,
- .size = SZ_256M - SZ_16M,
- },
- [HIGH_POOL] =
- /* Remaining address space up to 2G */
- {
- .paddr = SZ_256M,
- .size = SZ_2G - SZ_256M,
- }
};
static struct msm_iommu_domain msm_iommu_domains[] = {
- [GLOBAL_DOMAIN] = {
- .iova_pools = global_pools,
- .npools = ARRAY_SIZE(global_pools),
- }
};
int msm_iommu_map_extra(struct iommu_domain *domain,
@@ -281,10 +168,8 @@
int msm_use_iommu()
{
- /*
- * For now, just detect if the iommu is attached.
- */
- return iommu_found();
+ /* Kill use of the iommu by these clients for now. */
+ return 0;
}
static int __init msm_subsystem_iommu_init(void)
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 4b0d26a..6e8c99e 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -53,7 +53,7 @@
/* Load GNSS for Standalone 8064 but not for Fusion 3 */
if (cpu_is_apq8064()) {
if (socinfo_get_platform_subtype() == 0x0)
- pil = pil_get("gnss");
+ pil = pil_get("gss");
} else {
pil = pil_get("modem");
}
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index b672957..7445a61 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -455,6 +455,11 @@
mdm_drv->mdm_status_irq = irq;
status_err:
+ /* Perform early powerup of the external modem in order to
+ * allow tabla devices to be found.
+ */
+ mdm_drv->ops->power_on_mdm_cb(mdm_drv);
+
pr_info("%s: Registering mdm modem\n", __func__);
return misc_register(&mdm_modem_misc);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 46695c4..3b064ff 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -315,7 +315,12 @@
return 0;
mb = &meminfo.bank[meminfo.nr_banks - 1];
- fmem_phys = mb->start + (mb->size - fmem_size);
+ /*
+ * Placing fmem at the top of memory causes multimedia issues.
+ * Instead, place it 1 page below the top of memory to prevent
+ * the issues from occurring.
+ */
+ fmem_phys = mb->start + (mb->size - fmem_size) - PAGE_SIZE;
ret = memblock_remove(fmem_phys, fmem_size);
BUG_ON(ret);
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index d765f6a..f93a79b 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -65,6 +65,7 @@
struct msm_rtb_state msm_rtb = {
.size = SZ_1M,
+ .filter = 1 << LOGK_LOGBUF,
};
module_param_named(filter, msm_rtb.filter, uint, 0644);
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 5877fbf..5bff832 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -354,7 +354,7 @@
return ret;
}
- enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, 0);
+ enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
/*
* This is only temporary till SBLs turn on the XPUs
@@ -363,6 +363,9 @@
if (cpu_is_msm9615())
__raw_writel(0xF, MSM_TCSR_BASE + TCSR_WDT_CFG);
+ if (pdata->needs_expired_enable)
+ __raw_writel(0x1, MSM_CLK_CTL_BASE + 0x3820);
+
configure_bark_dump();
delay_time = msecs_to_jiffies(pdata->pet_time);
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 201c2b1..33e9e0c 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -19,6 +19,7 @@
/* bark timeout in ms */
unsigned int bark_time;
bool has_secure;
+ bool needs_expired_enable;
};
#ifdef CONFIG_MSM_WATCHDOG
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index af272af..74c64c1 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -115,7 +115,7 @@
static int msm_xo_update_vote(struct msm_xo *xo)
{
int ret;
- unsigned vote, prev_vote = xo->mode;
+ unsigned vote, prev_vote = xo->mode, ctx_set;
struct msm_rpm_iv_pair cmd;
if (xo->votes[MSM_XO_MODE_ON])
@@ -141,7 +141,11 @@
} else if (xo == &msm_xo_sources[MSM_XO_CXO]) {
cmd.id = MSM_RPM_ID_CXO_CLK;
cmd.value = msm_xo_sources[MSM_XO_CXO].mode ? 1 : 0;
- ret = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
+ if (cpu_is_msm9615())
+ ctx_set = MSM_RPM_CTX_SET_SLEEP;
+ else
+ ctx_set = MSM_RPM_CTX_SET_0;
+ ret = msm_rpmrs_set_noirq(ctx_set, &cmd, 1);
} else {
cmd.id = MSM_RPM_ID_CXO_BUFFERS;
cmd.value = (msm_xo_sources[MSM_XO_TCXO_D0].mode << 0) |
@@ -235,10 +239,9 @@
/*
* TODO: Remove early return for 8064 once RPM XO voting support
- * is available. Remove early return for 8960 CXO once all voters
- * for it are in place.
+ * is available.
*/
- if (cpu_is_apq8064() || (cpu_is_msm8960() && xo_id == MSM_XO_CXO))
+ if (cpu_is_apq8064())
return NULL;
if (xo_id >= NUM_MSM_XO_IDS) {
@@ -304,12 +307,25 @@
int __init msm_xo_init(void)
{
int i;
- int ret;
+ int ret = 0;
struct msm_rpm_iv_pair cmd[2];
for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++)
INIT_LIST_HEAD(&msm_xo_sources[i].voters);
+ if (cpu_is_msm9615()) {
+ cmd[0].id = MSM_RPM_ID_CXO_CLK;
+ cmd[0].value = 1;
+ ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, cmd, 1);
+ if (ret)
+ goto out;
+
+ cmd[0].id = MSM_RPM_ID_CXO_CLK;
+ cmd[0].value = 0;
+ ret = msm_rpmrs_set(MSM_RPM_CTX_SET_SLEEP, cmd, 1);
+ goto out;
+ }
+
cmd[0].id = MSM_RPM_ID_PXO_CLK;
cmd[0].value = 1;
cmd[1].id = MSM_RPM_ID_CXO_BUFFERS;
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 0886975..1004e01 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -288,14 +288,10 @@
mutex_lock(&pil->lock);
WARN(!pil->count, "%s: Reference count mismatch\n", __func__);
- /* TODO: Peripheral shutdown support */
- if (pil->count == 1)
- goto unlock;
if (pil->count)
pil->count--;
if (pil->count == 0)
pil->desc->ops->shutdown(pil->desc);
-unlock:
mutex_unlock(&pil->lock);
pil_d = find_peripheral(pil->desc->depends_on);
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index f3e83d9e..6ec9b5d7 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -257,6 +257,49 @@
.shutdown = pil_gss_shutdown,
};
+static int pil_gss_init_image_trusted(struct pil_desc *pil,
+ const u8 *metadata, size_t size)
+{
+ return pas_init_image(PAS_GSS, metadata, size);
+}
+
+static int pil_gss_reset_trusted(struct pil_desc *pil)
+{
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ int err;
+
+ err = make_gss_proxy_votes(pil->dev);
+ if (err)
+ return err;
+
+ err = pas_auth_and_reset(PAS_GSS);
+ if (err)
+ remove_gss_proxy_votes_now(drv);
+
+ return err;
+}
+
+static int pil_gss_shutdown_trusted(struct pil_desc *pil)
+{
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ int ret;
+
+ ret = pas_shutdown(PAS_GSS);
+ if (ret)
+ return ret;
+
+ remove_gss_proxy_votes_now(drv);
+
+ return ret;
+}
+
+static struct pil_reset_ops pil_gss_ops_trusted = {
+ .init_image = pil_gss_init_image_trusted,
+ .verify_blob = nop_verify_blob,
+ .auth_and_reset = pil_gss_reset_trusted,
+ .shutdown = pil_gss_shutdown_trusted,
+};
+
static void configure_gss_pll(struct gss_data *drv)
{
u32 regval, is_pll_enabled;
@@ -354,8 +397,13 @@
desc->name = "gss";
desc->dev = &pdev->dev;
- desc->ops = &pil_gss_ops;
- dev_info(&pdev->dev, "using non-secure boot\n");
+ if (pas_supported(PAS_GSS) > 0) {
+ desc->ops = &pil_gss_ops_trusted;
+ dev_info(&pdev->dev, "using secure boot\n");
+ } else {
+ desc->ops = &pil_gss_ops;
+ dev_info(&pdev->dev, "using non-secure boot\n");
+ }
INIT_DELAYED_WORK(&drv->work, remove_gss_proxy_votes);
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 3c422009..6b48d57 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -198,14 +198,5 @@
trace_hardirqs_off();
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- /* RUMI does not adhere to GIC spec by enabling STIs by default.
- * Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
- */
- if (!machine_is_msm8x60_sim())
- writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
gic_secondary_init(0);
}
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 4cdd7ae..e1934bb 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -3,7 +3,7 @@
* MSM Power Management Routines
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012 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
@@ -118,18 +118,6 @@
* Sleep Modes and Parameters
*****************************************************************************/
-static int msm_pm_sleep_mode = CONFIG_MSM7X00A_SLEEP_MODE;
-module_param_named(
- sleep_mode, msm_pm_sleep_mode,
- int, S_IRUGO | S_IWUSR | S_IWGRP
-);
-
-static int msm_pm_idle_sleep_mode = CONFIG_MSM7X00A_IDLE_SLEEP_MODE;
-module_param_named(
- idle_sleep_mode, msm_pm_idle_sleep_mode,
- int, S_IRUGO | S_IWUSR | S_IWGRP
-);
-
static int msm_pm_idle_sleep_min_time = CONFIG_MSM7X00A_IDLE_SLEEP_MIN_TIME;
module_param_named(
idle_sleep_min_time, msm_pm_idle_sleep_min_time,
@@ -166,10 +154,20 @@
static struct msm_pm_platform_data *msm_pm_modes;
-static struct kobject *msm_pm_mode_kobjs[MSM_PM_SLEEP_MODE_NR];
-static struct attribute_group *msm_pm_mode_attr_group[MSM_PM_SLEEP_MODE_NR];
-static struct attribute **msm_pm_mode_attrs[MSM_PM_SLEEP_MODE_NR];
-static struct kobj_attribute *msm_pm_mode_kobj_attrs[MSM_PM_SLEEP_MODE_NR];
+struct msm_pm_kobj_attribute {
+ unsigned int cpu;
+ struct kobj_attribute ka;
+};
+
+#define GET_CPU_OF_ATTR(attr) \
+ (container_of(attr, struct msm_pm_kobj_attribute, ka)->cpu)
+
+struct msm_pm_sysfs_sleep_mode {
+ struct kobject *kobj;
+ struct attribute_group attr_group;
+ struct attribute *attrs[MSM_PM_MODE_ATTR_NR + 1];
+ struct msm_pm_kobj_attribute kas[MSM_PM_MODE_ATTR_NR];
+};
/*
* Write out the attribute.
@@ -182,6 +180,8 @@
for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
struct kernel_param kp;
+ unsigned int cpu;
+ struct msm_pm_platform_data *mode;
if (msm_pm_sleep_mode_labels[i] == NULL)
continue;
@@ -189,23 +189,28 @@
if (strcmp(kobj->name, msm_pm_sleep_mode_labels[i]))
continue;
+ cpu = GET_CPU_OF_ATTR(attr);
+ mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+
if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
- u32 arg = msm_pm_modes[i].suspend_enabled;
+ u32 arg = mode->suspend_enabled;
kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_IDLE])) {
- u32 arg = msm_pm_modes[i].idle_enabled;
+ u32 arg = mode->idle_enabled;
kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_LATENCY])) {
- kp.arg = &msm_pm_modes[i].latency;
+ u32 arg = mode->latency;
+ kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_RESIDENCY])) {
- kp.arg = &msm_pm_modes[i].residency;
+ u32 arg = mode->residency;
+ kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
}
@@ -213,7 +218,7 @@
}
if (ret > 0) {
- strcat(buf, "\n");
+ strlcat(buf, "\n", PAGE_SIZE);
ret++;
}
@@ -231,6 +236,8 @@
for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
struct kernel_param kp;
+ unsigned int cpu;
+ struct msm_pm_platform_data *mode;
if (msm_pm_sleep_mode_labels[i] == NULL)
continue;
@@ -238,21 +245,24 @@
if (strcmp(kobj->name, msm_pm_sleep_mode_labels[i]))
continue;
+ cpu = GET_CPU_OF_ATTR(attr);
+ mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+
if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
- kp.arg = &msm_pm_modes[i].suspend_enabled;
+ kp.arg = &mode->suspend_enabled;
ret = param_set_byte(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_IDLE])) {
- kp.arg = &msm_pm_modes[i].idle_enabled;
+ kp.arg = &mode->idle_enabled;
ret = param_set_byte(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_LATENCY])) {
- kp.arg = &msm_pm_modes[i].latency;
+ kp.arg = &mode->latency;
ret = param_set_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_RESIDENCY])) {
- kp.arg = &msm_pm_modes[i].residency;
+ kp.arg = &mode->residency;
ret = param_set_ulong(buf, &kp);
}
@@ -262,6 +272,86 @@
return ret ? ret : count;
}
+ /* Add sysfs entries for one cpu. */
+static int __init msm_pm_mode_sysfs_add_cpu(
+ unsigned int cpu, struct kobject *modes_kobj)
+{
+ char cpu_name[8];
+ struct kobject *cpu_kobj;
+ struct msm_pm_sysfs_sleep_mode *mode = NULL;
+ int i, j, k;
+ int ret;
+
+ snprintf(cpu_name, sizeof(cpu_name), "cpu%u", cpu);
+ cpu_kobj = kobject_create_and_add(cpu_name, modes_kobj);
+ if (!cpu_kobj) {
+ pr_err("%s: cannot create %s kobject\n", __func__, cpu_name);
+ ret = -ENOMEM;
+ goto mode_sysfs_add_cpu_exit;
+ }
+
+ for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
+ int idx = MSM_PM_MODE(cpu, i);
+
+ if ((!msm_pm_modes[idx].suspend_supported) &&
+ (!msm_pm_modes[idx].idle_supported))
+ continue;
+
+ mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+ if (!mode) {
+ pr_err("%s: cannot allocate memory for attributes\n",
+ __func__);
+ ret = -ENOMEM;
+ goto mode_sysfs_add_cpu_exit;
+ }
+
+ mode->kobj = kobject_create_and_add(
+ msm_pm_sleep_mode_labels[i], cpu_kobj);
+ if (!mode->kobj) {
+ pr_err("%s: cannot create kobject\n", __func__);
+ ret = -ENOMEM;
+ goto mode_sysfs_add_cpu_exit;
+ }
+
+ for (k = 0, j = 0; k < MSM_PM_MODE_ATTR_NR; k++) {
+ if ((k == MSM_PM_MODE_ATTR_IDLE) &&
+ !msm_pm_modes[idx].idle_supported)
+ continue;
+ if ((k == MSM_PM_MODE_ATTR_SUSPEND) &&
+ !msm_pm_modes[idx].suspend_supported)
+ continue;
+ mode->kas[j].cpu = cpu;
+ mode->kas[j].ka.attr.mode = 0644;
+ mode->kas[j].ka.show = msm_pm_mode_attr_show;
+ mode->kas[j].ka.store = msm_pm_mode_attr_store;
+ mode->kas[j].ka.attr.name = msm_pm_mode_attr_labels[k];
+ mode->attrs[j] = &mode->kas[j].ka.attr;
+ j++;
+ }
+ mode->attrs[j] = NULL;
+
+ mode->attr_group.attrs = mode->attrs;
+ ret = sysfs_create_group(mode->kobj, &mode->attr_group);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: cannot create kobject attribute group\n",
+ __func__);
+ goto mode_sysfs_add_cpu_exit;
+ }
+ }
+
+ ret = 0;
+
+mode_sysfs_add_cpu_exit:
+ if (ret) {
+ if (mode && mode->kobj)
+ kobject_del(mode->kobj);
+ kfree(mode);
+ }
+
+ return ret;
+}
+
/*
* Add sysfs entries for the sleep modes.
*/
@@ -269,13 +359,7 @@
{
struct kobject *module_kobj = NULL;
struct kobject *modes_kobj = NULL;
-
- struct kobject *kobj;
- struct attribute_group *attr_group;
- struct attribute **attrs;
- struct kobj_attribute *kobj_attrs;
-
- int i, j, k;
+ unsigned int cpu;
int ret;
module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
@@ -283,98 +367,32 @@
printk(KERN_ERR "%s: cannot find kobject for module %s\n",
__func__, KBUILD_MODNAME);
ret = -ENOENT;
- goto mode_sysfs_add_cleanup;
+ goto mode_sysfs_add_exit;
}
modes_kobj = kobject_create_and_add("modes", module_kobj);
if (!modes_kobj) {
printk(KERN_ERR "%s: cannot create modes kobject\n", __func__);
ret = -ENOMEM;
- goto mode_sysfs_add_cleanup;
+ goto mode_sysfs_add_exit;
}
- for (i = 0; i < ARRAY_SIZE(msm_pm_mode_kobjs); i++) {
- if (!msm_pm_modes[i].suspend_supported &&
- !msm_pm_modes[i].idle_supported)
- continue;
-
- kobj = kobject_create_and_add(
- msm_pm_sleep_mode_labels[i], modes_kobj);
- attr_group = kzalloc(sizeof(*attr_group), GFP_KERNEL);
- attrs = kzalloc(sizeof(*attrs) * (MSM_PM_MODE_ATTR_NR + 1),
- GFP_KERNEL);
- kobj_attrs = kzalloc(sizeof(*kobj_attrs) * MSM_PM_MODE_ATTR_NR,
- GFP_KERNEL);
-
- if (!kobj || !attr_group || !attrs || !kobj_attrs) {
- printk(KERN_ERR
- "%s: cannot create kobject or attributes\n",
- __func__);
- ret = -ENOMEM;
- goto mode_sysfs_add_abort;
- }
-
- for (k = 0, j = 0; k < MSM_PM_MODE_ATTR_NR; k++) {
- if ((k == MSM_PM_MODE_ATTR_SUSPEND) &&
- (!msm_pm_modes[i].suspend_supported))
- continue;
- if ((k == MSM_PM_MODE_ATTR_IDLE) &&
- (!msm_pm_modes[i].idle_supported))
- continue;
-
- kobj_attrs[j].attr.mode = 0644;
- kobj_attrs[j].show = msm_pm_mode_attr_show;
- kobj_attrs[j].store = msm_pm_mode_attr_store;
- kobj_attrs[j].attr.name = msm_pm_mode_attr_labels[k];
- attrs[j] = &kobj_attrs[j].attr;
- j++;
- }
- attrs[j] = NULL;
-
- attr_group->attrs = attrs;
- ret = sysfs_create_group(kobj, attr_group);
- if (ret) {
- printk(KERN_ERR
- "%s: cannot create kobject attribute group\n",
- __func__);
- goto mode_sysfs_add_abort;
- }
-
- msm_pm_mode_kobjs[i] = kobj;
- msm_pm_mode_attr_group[i] = attr_group;
- msm_pm_mode_attrs[i] = attrs;
- msm_pm_mode_kobj_attrs[i] = kobj_attrs;
+ for_each_possible_cpu(cpu) {
+ ret = msm_pm_mode_sysfs_add_cpu(cpu, modes_kobj);
+ if (ret)
+ goto mode_sysfs_add_exit;
}
- return 0;
+ ret = 0;
-mode_sysfs_add_abort:
- kfree(kobj_attrs);
- kfree(attrs);
- kfree(attr_group);
- kobject_put(kobj);
-
-mode_sysfs_add_cleanup:
- for (i = ARRAY_SIZE(msm_pm_mode_kobjs) - 1; i >= 0; i--) {
- if (!msm_pm_mode_kobjs[i])
- continue;
-
- sysfs_remove_group(
- msm_pm_mode_kobjs[i], msm_pm_mode_attr_group[i]);
-
- kfree(msm_pm_mode_kobj_attrs[i]);
- kfree(msm_pm_mode_attrs[i]);
- kfree(msm_pm_mode_attr_group[i]);
- kobject_put(msm_pm_mode_kobjs[i]);
- }
-
+mode_sysfs_add_exit:
return ret;
}
void __init msm_pm_set_platform_data(
struct msm_pm_platform_data *data, int count)
{
- BUG_ON(MSM_PM_SLEEP_MODE_NR != count);
+ BUG_ON(MSM_PM_SLEEP_MODE_NR * num_possible_cpus() > count);
msm_pm_modes = data;
}
@@ -674,7 +692,7 @@
MSM_PM_STAT_COUNT
};
-static struct msm_pm_time_stats {
+struct msm_pm_time_stats {
const char *name;
int64_t first_bucket_time;
int bucket[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
@@ -682,74 +700,37 @@
int64_t max_time[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
int count;
int64_t total_time;
-} msm_pm_stats[MSM_PM_STAT_COUNT] = {
- [MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request",
- [MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_SPIN].name = "idle-spin",
- [MSM_PM_STAT_IDLE_SPIN].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_WFI].name = "idle-wfi",
- [MSM_PM_STAT_IDLE_WFI].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name =
- "idle-standalone-power-collapse",
- [MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].name =
- "idle-failed-standalone-power-collapse",
- [MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep",
- [MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_FAILED_SLEEP].name = "idle-failed-sleep",
- [MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_POWER_COLLAPSE].name = "idle-power-collapse",
- [MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name =
- "idle-failed-power-collapse",
- [MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_SUSPEND].name = "suspend",
- [MSM_PM_STAT_SUSPEND].first_bucket_time =
- CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend",
- [MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_NOT_IDLE].name = "not-idle",
- [MSM_PM_STAT_NOT_IDLE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
};
+struct msm_pm_cpu_time_stats {
+ struct msm_pm_time_stats stats[MSM_PM_STAT_COUNT];
+};
+
+static DEFINE_PER_CPU_SHARED_ALIGNED(
+ struct msm_pm_cpu_time_stats, msm_pm_stats);
+
static uint32_t msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
+static DEFINE_SPINLOCK(msm_pm_stats_lock);
+
/*
* Add the given time data to the statistics collection.
*/
static void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t)
{
+ unsigned long flags;
+ struct msm_pm_time_stats *stats;
int i;
int64_t bt;
- msm_pm_stats[id].total_time += t;
- msm_pm_stats[id].count++;
+ spin_lock_irqsave(&msm_pm_stats_lock, flags);
+ stats = __get_cpu_var(msm_pm_stats).stats;
+
+ stats[id].total_time += t;
+ stats[id].count++;
bt = t;
- do_div(bt, msm_pm_stats[id].first_bucket_time);
+ do_div(bt, stats[id].first_bucket_time);
if (bt < 1ULL << (CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT *
(CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1)))
@@ -758,12 +739,17 @@
else
i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
- msm_pm_stats[id].bucket[i]++;
+ if (i >= CONFIG_MSM_IDLE_STATS_BUCKET_COUNT)
+ i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
- if (t < msm_pm_stats[id].min_time[i] || !msm_pm_stats[id].max_time[i])
- msm_pm_stats[id].min_time[i] = t;
- if (t > msm_pm_stats[id].max_time[i])
- msm_pm_stats[id].max_time[i] = t;
+ stats[id].bucket[i]++;
+
+ if (t < stats[id].min_time[i] || !stats[id].max_time[i])
+ stats[id].min_time[i] = t;
+ if (t > stats[id].max_time[i])
+ stats[id].max_time[i] = t;
+
+ spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
}
/*
@@ -793,7 +779,8 @@
static int msm_pm_read_proc
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- int i;
+ unsigned int cpu = off / MSM_PM_STAT_COUNT;
+ int id = off % MSM_PM_STAT_COUNT;
char *p = page;
if (count < 1024) {
@@ -809,44 +796,51 @@
SNPRINTF(p, count, "for TCXO shutdown\n\n");
else
SNPRINTF(p, count, "against TCXO shutdown\n\n");
+ }
- *start = (char *) 1;
- *eof = 0;
- } else if (--off < ARRAY_SIZE(msm_pm_stats)) {
+ if (cpu < num_possible_cpus()) {
+ unsigned long flags;
+ struct msm_pm_time_stats *stats;
+ int i;
int64_t bucket_time;
int64_t s;
uint32_t ns;
- s = msm_pm_stats[off].total_time;
+ spin_lock_irqsave(&msm_pm_stats_lock, flags);
+ stats = per_cpu(msm_pm_stats, cpu).stats;
+
+ s = stats[id].total_time;
ns = do_div(s, NSEC_PER_SEC);
SNPRINTF(p, count,
- "%s:\n"
+ "[cpu %u] %s:\n"
" count: %7d\n"
" total_time: %lld.%09u\n",
- msm_pm_stats[off].name,
- msm_pm_stats[off].count,
+ cpu, stats[id].name,
+ stats[id].count,
s, ns);
- bucket_time = msm_pm_stats[off].first_bucket_time;
+ bucket_time = stats[id].first_bucket_time;
for (i = 0; i < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; i++) {
s = bucket_time;
ns = do_div(s, NSEC_PER_SEC);
SNPRINTF(p, count,
" <%6lld.%09u: %7d (%lld-%lld)\n",
- s, ns, msm_pm_stats[off].bucket[i],
- msm_pm_stats[off].min_time[i],
- msm_pm_stats[off].max_time[i]);
+ s, ns, stats[id].bucket[i],
+ stats[id].min_time[i],
+ stats[id].max_time[i]);
bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT;
}
SNPRINTF(p, count, " >=%6lld.%09u: %7d (%lld-%lld)\n",
- s, ns, msm_pm_stats[off].bucket[i],
- msm_pm_stats[off].min_time[i],
- msm_pm_stats[off].max_time[i]);
+ s, ns, stats[id].bucket[i],
+ stats[id].min_time[i],
+ stats[id].max_time[i]);
*start = (char *) 1;
- *eof = (off + 1 >= ARRAY_SIZE(msm_pm_stats));
+ *eof = (off + 1 >= MSM_PM_STAT_COUNT * num_possible_cpus());
+
+ spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
}
return p - page;
@@ -864,7 +858,7 @@
char buf[sizeof(MSM_PM_STATS_RESET)];
int ret;
unsigned long flags;
- int i;
+ unsigned int cpu;
if (count < strlen(MSM_PM_STATS_RESET)) {
ret = -EINVAL;
@@ -881,26 +875,32 @@
goto write_proc_failed;
}
- local_irq_save(flags);
- for (i = 0; i < ARRAY_SIZE(msm_pm_stats); i++) {
- memset(msm_pm_stats[i].bucket,
- 0, sizeof(msm_pm_stats[i].bucket));
- memset(msm_pm_stats[i].min_time,
- 0, sizeof(msm_pm_stats[i].min_time));
- memset(msm_pm_stats[i].max_time,
- 0, sizeof(msm_pm_stats[i].max_time));
- msm_pm_stats[i].count = 0;
- msm_pm_stats[i].total_time = 0;
- }
+ spin_lock_irqsave(&msm_pm_stats_lock, flags);
+ for_each_possible_cpu(cpu) {
+ struct msm_pm_time_stats *stats;
+ int i;
+ stats = per_cpu(msm_pm_stats, cpu).stats;
+ for (i = 0; i < MSM_PM_STAT_COUNT; i++) {
+ memset(stats[i].bucket,
+ 0, sizeof(stats[i].bucket));
+ memset(stats[i].min_time,
+ 0, sizeof(stats[i].min_time));
+ memset(stats[i].max_time,
+ 0, sizeof(stats[i].max_time));
+ stats[i].count = 0;
+ stats[i].total_time = 0;
+ }
+ }
msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
return count;
write_proc_failed:
return ret;
}
+
#undef MSM_PM_STATS_RESET
#endif /* CONFIG_MSM_IDLE_STATS */
@@ -1389,16 +1389,19 @@
int low_power;
int ret;
int i;
+ unsigned int cpu;
#ifdef CONFIG_MSM_IDLE_STATS
int64_t t1;
static int64_t t2;
int exit_stat;
-#endif /* CONFIG_MSM_IDLE_STATS */
+ #endif /* CONFIG_MSM_IDLE_STATS */
if (!atomic_read(&msm_pm_init_done))
return;
+ cpu = smp_processor_id();
+
latency_qos = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
timer_expiration = msm_timer_enter_idle();
@@ -1406,39 +1409,14 @@
t1 = ktime_to_ns(ktime_get());
msm_pm_add_stat(MSM_PM_STAT_NOT_IDLE, t1 - t2);
msm_pm_add_stat(MSM_PM_STAT_REQUESTED_IDLE, timer_expiration);
+
+ exit_stat = MSM_PM_STAT_IDLE_SPIN;
+ low_power = 0;
#endif /* CONFIG_MSM_IDLE_STATS */
for (i = 0; i < ARRAY_SIZE(allow); i++)
allow[i] = true;
- switch (msm_pm_idle_sleep_mode) {
- case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
- allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] =
- false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
- allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] = false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
- allow[MSM_PM_SLEEP_MODE_APPS_SLEEP] = false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_APPS_SLEEP:
- allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false;
- allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
- break;
- default:
- printk(KERN_ERR "idle sleep mode is invalid: %d\n",
- msm_pm_idle_sleep_mode);
-#ifdef CONFIG_MSM_IDLE_STATS
- exit_stat = MSM_PM_STAT_IDLE_SPIN;
-#endif /* CONFIG_MSM_IDLE_STATS */
- low_power = 0;
- goto arch_idle_exit;
- }
-
if ((timer_expiration < msm_pm_idle_sleep_min_time) ||
#ifdef CONFIG_HAS_WAKELOCK
has_wake_lock(WAKE_LOCK_IDLE) ||
@@ -1450,7 +1428,8 @@
}
for (i = 0; i < ARRAY_SIZE(allow); i++) {
- struct msm_pm_platform_data *mode = &msm_pm_modes[i];
+ struct msm_pm_platform_data *mode =
+ &msm_pm_modes[MSM_PM_MODE(cpu, i)];
if (!mode->idle_supported || !mode->idle_enabled ||
mode->latency >= latency_qos ||
mode->residency * 1000ULL >= timer_expiration)
@@ -1564,7 +1543,6 @@
#endif /* CONFIG_MSM_IDLE_STATS */
}
-arch_idle_exit:
msm_timer_exit_idle(low_power);
#ifdef CONFIG_MSM_IDLE_STATS
@@ -1604,32 +1582,9 @@
for (i = 0; i < ARRAY_SIZE(allow); i++)
allow[i] = true;
- switch (msm_pm_sleep_mode) {
- case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
- allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] =
- false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
- allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE] = false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
- allow[MSM_PM_SLEEP_MODE_APPS_SLEEP] = false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_APPS_SLEEP:
- allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false;
- allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false;
- /* fall through */
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
- break;
- default:
- printk(KERN_ERR "suspend sleep mode is invalid: %d\n",
- msm_pm_sleep_mode);
- return -EINVAL;
- }
-
for (i = 0; i < ARRAY_SIZE(allow); i++) {
- struct msm_pm_platform_data *mode = &msm_pm_modes[i];
+ struct msm_pm_platform_data *mode;
+ mode = &msm_pm_modes[MSM_PM_MODE(0, i)];
if (!mode->suspend_supported || !mode->suspend_enabled)
allow[i] = false;
}
@@ -1778,6 +1733,7 @@
{
#ifdef CONFIG_MSM_IDLE_STATS
struct proc_dir_entry *d_entry;
+ unsigned int cpu;
#endif
int ret;
#ifdef CONFIG_CPU_V7
@@ -1846,6 +1802,66 @@
msm_pm_mode_sysfs_add();
#ifdef CONFIG_MSM_IDLE_STATS
+ for_each_possible_cpu(cpu) {
+ struct msm_pm_time_stats *stats =
+ per_cpu(msm_pm_stats, cpu).stats;
+
+ stats[MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request";
+ stats[MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_SPIN].name = "idle-spin";
+ stats[MSM_PM_STAT_IDLE_SPIN].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_WFI].name = "idle-wfi";
+ stats[MSM_PM_STAT_IDLE_WFI].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name =
+ "idle-standalone-power-collapse";
+ stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].
+ first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].name =
+ "idle-failed-standalone-power-collapse";
+ stats[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].
+ first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep";
+ stats[MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].name =
+ "idle-failed-sleep";
+ stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].name =
+ "idle-power-collapse";
+ stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name =
+ "idle-failed-power-collapse";
+ stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].
+ first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_SUSPEND].name = "suspend";
+ stats[MSM_PM_STAT_SUSPEND].first_bucket_time =
+ CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend";
+ stats[MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_NOT_IDLE].name = "not-idle";
+ stats[MSM_PM_STAT_NOT_IDLE].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+ }
d_entry = create_proc_entry("msm_pm_stats",
S_IRUGO | S_IWUSR | S_IWGRP, NULL);
if (d_entry) {
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 946d31b..ed366aed 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -268,8 +268,10 @@
if (vreg->part->uV.mask)
uV = GET_PART(vreg, uV);
- else
+ else if (vreg->part->mV.mask)
uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
+ else if (vreg->part->enable_state.mask)
+ uV = GET_PART(vreg, enable_state);
return uV;
}
@@ -278,8 +280,10 @@
{
if (vreg->part->uV.mask)
SET_PART(vreg, uV, uV);
- else
+ else if (vreg->part->mV.mask)
SET_PART(vreg, mV, MICRO_TO_MILLI(uV));
+ else if (vreg->part->enable_state.mask)
+ SET_PART(vreg, enable_state, uV);
}
static int vreg_send_request(struct vreg *vreg, enum rpm_vreg_voter voter,
@@ -380,9 +384,14 @@
if (vreg->part->uV.mask) {
s_val[vreg->part->uV.word] = 0 << vreg->part->uV.shift;
s_mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
+ } else if (vreg->part->mV.mask) {
s_val[vreg->part->mV.word] = 0 << vreg->part->mV.shift;
s_mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ } else if (vreg->part->enable_state.mask) {
+ s_val[vreg->part->enable_state.word]
+ = 0 << vreg->part->enable_state.shift;
+ s_mask[vreg->part->enable_state.word]
+ = vreg->part->enable_state.mask;
}
rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
@@ -421,6 +430,10 @@
*
* Consumers can vote to disable a regulator with this function by passing
* min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well. For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
*/
int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
int max_uV, int sleep_also)
@@ -431,14 +444,6 @@
int uV = min_uV;
int lim_min_uV, lim_max_uV, i, rc;
- /*
- * HACK: make this function a no-op for 8064 so that it can be called by
- * consumers on 8064 before RPM capabilities are present. (needed for
- * acpuclock driver)
- */
- if (cpu_is_apq8064())
- return 0;
-
if (!config) {
pr_err("rpm-regulator driver has not probed yet.\n");
return -ENODEV;
@@ -450,7 +455,6 @@
}
vreg = &config->vregs[vreg_id];
- range = &vreg->set_points->range[0];
if (!vreg->pdata.sleep_selectable) {
vreg_err(vreg, "regulator is not marked sleep selectable\n");
@@ -458,7 +462,8 @@
}
/* Allow min_uV == max_uV == 0 to represent a disable request. */
- if (min_uV != 0 || max_uV != 0) {
+ if ((min_uV != 0 || max_uV != 0)
+ && (vreg->part->uV.mask || vreg->part->mV.mask)) {
/*
* Check if request voltage is outside of allowed range. The
* regulator core has already checked that constraint range
@@ -477,6 +482,7 @@
return -EINVAL;
}
+ range = &vreg->set_points->range[0];
/* Find the range which uV is inside of. */
for (i = vreg->set_points->count - 1; i > 0; i--) {
if (uV > vreg->set_points->range[i - 1].max_uV) {
@@ -504,10 +510,20 @@
if (vreg->part->uV.mask) {
val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
+ } else if (vreg->part->mV.mask) {
val[vreg->part->mV.word]
= MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ } else if (vreg->part->enable_state.mask) {
+ /*
+ * Translate max_uV > 0 into an enable request for regulator
+ * types which to not support voltage setting, e.g. voltage
+ * switches.
+ */
+ val[vreg->part->enable_state.word]
+ = (max_uV > 0 ? 1 : 0) << vreg->part->enable_state.shift;
+ mask[vreg->part->enable_state.word]
+ = vreg->part->enable_state.mask;
}
rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],
@@ -532,13 +548,6 @@
struct vreg *vreg;
int rc;
- /*
- * HACK: make this function a no-op for 8064 so that it can be called by
- * consumers on 8064 before RPM capabilities are present.
- */
- if (cpu_is_apq8064())
- return 0;
-
if (!config) {
pr_err("rpm-regulator driver has not probed yet.\n");
return -ENODEV;
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index fb9d295..05b2953 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.c
@@ -31,7 +31,6 @@
#include <asm/hardware/gic.h>
#include <mach/msm_iomap.h>
#include <mach/rpm.h>
-#include <mach/socinfo.h>
/******************************************************************************
* Data type and structure definitions
@@ -425,9 +424,6 @@
uint32_t sel_masks[SEL_MASK_SIZE] = {};
int rc;
- if (cpu_is_apq8064())
- return 0;
-
if (ctx >= MSM_RPM_CTX_SET_COUNT) {
rc = -EINVAL;
goto set_common_exit;
@@ -471,9 +467,6 @@
int rc;
int i;
- if (cpu_is_apq8064())
- return 0;
-
if (ctx >= MSM_RPM_CTX_SET_COUNT) {
rc = -EINVAL;
goto clear_common_exit;
@@ -612,9 +605,6 @@
int rc;
int i;
- if (cpu_is_apq8064())
- return 0;
-
seq_begin = msm_rpm_read(MSM_RPM_PAGE_STATUS,
target_status(MSM_RPM_STATUS_ID_SEQUENCE));
@@ -768,9 +758,6 @@
int rc;
int i;
- if (cpu_is_apq8064())
- return 0;
-
INIT_LIST_HEAD(&n->list);
rc = msm_rpm_fill_sel_masks(n->sel_masks, req, count);
if (rc)
@@ -823,9 +810,6 @@
int rc;
int i;
- if (cpu_is_apq8064())
- return 0;
-
rc = mutex_lock_interruptible(&msm_rpm_mutex);
if (rc)
goto unregister_notification_exit;
@@ -951,9 +935,6 @@
unsigned int irq;
int rc;
- if (cpu_is_apq8064())
- return 0;
-
memcpy(&msm_rpm_data, data, sizeof(struct msm_rpm_platform_data));
msm_rpm_sel_mask_size = msm_rpm_data.sel_last / 32 + 1;
BUG_ON(SEL_MASK_SIZE < msm_rpm_sel_mask_size);
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 609528c..546a917 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1016,12 +1016,13 @@
/* Initialize listed bitmap for valid resource IDs */
for (i = 0; i < ARRAY_SIZE(msm_rpmrs_resources); i++) {
- for (k = 0; k < msm_rpmrs_resources[i]->size; k++)
+ for (k = 0; k < msm_rpmrs_resources[i]->size; k++) {
if (msm_rpmrs_resources[i]->rs[k].id >=
MSM_RPM_ID_LAST)
continue;
set_bit(msm_rpmrs_resources[i]->rs[k].id,
msm_rpmrs_listed);
+ }
}
return 0;
@@ -1032,9 +1033,6 @@
struct msm_rpm_iv_pair req;
int rc;
- if (cpu_is_apq8064())
- return -ENODEV;
-
BUG_ON(!msm_rpmrs_levels);
if (cpu_is_msm8x60()) {
@@ -1068,7 +1066,7 @@
static int __init msm_rpmrs_l2_init(void)
{
- if (cpu_is_msm8960() || cpu_is_msm8930()) {
+ if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064()) {
msm_pm_set_l2_flush_flag(0);
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index 67a0992..3651ee19 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
PAS_MODEM_SW,
PAS_MODEM_FW,
PAS_RIVA,
+ PAS_SECAPP,
+ PAS_GSS,
};
extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 10593c62..b95c3aa 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -102,6 +102,45 @@
uint32_t last_value;
};
+struct interrupt_config_item {
+ /* must be initialized */
+ irqreturn_t (*irq_handler)(int req, void *data);
+ /* outgoing interrupt config (set from platform data) */
+ uint32_t out_bit_pos;
+ void __iomem *out_base;
+ uint32_t out_offset;
+};
+
+struct interrupt_config {
+ struct interrupt_config_item smd;
+ struct interrupt_config_item smsm;
+};
+
+static irqreturn_t smd_modem_irq_handler(int irq, void *data);
+static irqreturn_t smd_dsp_irq_handler(int irq, void *data);
+static irqreturn_t smd_dsps_irq_handler(int irq, void *data);
+static irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
+static irqreturn_t smsm_irq_handler(int irq, void *data);
+
+static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
+ [SMD_MODEM] = {
+ .smd.irq_handler = smd_modem_irq_handler,
+ .smsm.irq_handler = smsm_irq_handler,
+ },
+ [SMD_Q6] = {
+ .smd.irq_handler = smd_dsp_irq_handler,
+ .smsm.irq_handler = smsm_irq_handler,
+ },
+ [SMD_DSPS] = {
+ .smd.irq_handler = smd_dsps_irq_handler,
+ .smsm.irq_handler = smsm_irq_handler,
+ },
+ [SMD_WCNSS] = {
+ .smd.irq_handler = smd_wcnss_irq_handler,
+ .smsm.irq_handler = smsm_irq_handler,
+ },
+};
+
#define SMSM_STATE_ADDR(entry) (smsm_info.state + entry)
#define SMSM_INTR_MASK_ADDR(entry, host) (smsm_info.intr_mask + \
entry * SMSM_NUM_HOSTS + host)
@@ -240,7 +279,6 @@
static remote_spinlock_t remote_spinlock;
static LIST_HEAD(smd_ch_list_loopback);
-static irqreturn_t smsm_irq_handler(int irq, void *data);
static void smd_fake_irq_handler(unsigned long arg);
static void smsm_cb_snapshot(void);
@@ -275,6 +313,98 @@
static inline void wakeup_v1_riva(void) {}
#endif
+static inline void notify_modem_smd(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_MODEM].smd;
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2M_SMD_INT;
+}
+
+static inline void notify_dsp_smd(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_Q6].smd;
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2Q6_SMD_INT;
+}
+
+static inline void notify_dsps_smd(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_DSPS].smd;
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2DSPS_SMD_INT;
+}
+
+static inline void notify_wcnss_smd(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_WCNSS].smd;
+ wakeup_v1_riva();
+
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2WCNSS_SMD_INT;
+}
+
+static inline void notify_modem_smsm(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_MODEM].smsm;
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2M_SMSM_INT;
+}
+
+static inline void notify_dsp_smsm(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_Q6].smsm;
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2Q6_SMSM_INT;
+}
+
+static inline void notify_dsps_smsm(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_DSPS].smsm;
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2DSPS_SMSM_INT;
+}
+
+static inline void notify_wcnss_smsm(void)
+{
+ static const struct interrupt_config_item *intr
+ = &private_intr_config[SMD_WCNSS].smsm;
+ wakeup_v1_riva();
+
+ if (intr->out_base)
+ smd_write_intr(intr->out_bit_pos,
+ intr->out_base + intr->out_offset);
+ else
+ MSM_TRIG_A2WCNSS_SMSM_INT;
+}
+
static void notify_other_smsm(uint32_t smsm_entry, uint32_t notify_mask)
{
/* older protocol don't use smsm_intr_mask,
@@ -282,7 +412,7 @@
if (!smsm_info.intr_mask ||
(__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_MODEM))
& notify_mask))
- MSM_TRIG_A2M_SMSM_INT;
+ notify_modem_smsm();
if (smsm_info.intr_mask &&
(__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_Q6))
@@ -296,46 +426,24 @@
__raw_writel(mux_val,
SMSM_INTR_MUX_ADDR(SMEM_APPS_Q6_SMSM));
}
- MSM_TRIG_A2Q6_SMSM_INT;
+ notify_dsp_smsm();
}
if (smsm_info.intr_mask &&
(__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_WCNSS))
& notify_mask)) {
- wakeup_v1_riva();
- MSM_TRIG_A2WCNSS_SMSM_INT;
+ notify_wcnss_smsm();
}
if (smsm_info.intr_mask &&
(__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_DSPS))
& notify_mask)) {
- MSM_TRIG_A2DSPS_SMSM_INT;
+ notify_dsps_smsm();
}
smsm_cb_snapshot();
}
-static inline void notify_modem_smd(void)
-{
- MSM_TRIG_A2M_SMD_INT;
-}
-
-static inline void notify_dsp_smd(void)
-{
- MSM_TRIG_A2Q6_SMD_INT;
-}
-
-static inline void notify_dsps_smd(void)
-{
- MSM_TRIG_A2DSPS_SMD_INT;
-}
-
-static inline void notify_wcnss_smd(void)
-{
- wakeup_v1_riva();
- MSM_TRIG_A2WCNSS_SMD_INT;
-}
-
void smd_diag(void)
{
char *x;
@@ -451,23 +559,6 @@
uint32_t remote_pid;
};
-/*
- * SMD Processor ID's.
- *
- * For all processors that have both SMSM and SMD clients,
- * the SMSM Processor ID and the SMD Processor ID will
- * be the same. In cases where a processor only supports
- * SMD, the entry will only exist in this enum.
- */
-enum {
- SMD_APPS = SMSM_APPS,
- SMD_MODEM = SMSM_MODEM,
- SMD_Q6 = SMSM_Q6,
- SMD_WCNSS = SMSM_WCNSS,
- SMD_DSPS = SMSM_DSPS,
- SMD_MODEM_Q6_FW,
-};
-
/**
* Maps edge type to local and remote processor ID's.
*/
@@ -1008,32 +1099,26 @@
return IRQ_HANDLED;
}
-#if defined(CONFIG_QDSP6)
static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
{
handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
handle_smd_irq_closing_list();
return IRQ_HANDLED;
}
-#endif
-#if defined(CONFIG_DSPS)
static irqreturn_t smd_dsps_irq_handler(int irq, void *data)
{
handle_smd_irq(&smd_ch_list_dsps, notify_dsps_smd);
handle_smd_irq_closing_list();
return IRQ_HANDLED;
}
-#endif
-#if defined(CONFIG_WCNSS)
static irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
{
handle_smd_irq(&smd_ch_list_wcnss, notify_wcnss_smd);
handle_smd_irq_closing_list();
return IRQ_HANDLED;
}
-#endif
static void smd_fake_irq_handler(unsigned long arg)
{
@@ -2567,22 +2652,121 @@
pr_err("smd_core_init: "
"enable_irq_wake failed for INT_DSPS_A11_SMSM\n");
#endif
-
- /* we may have missed a signal while booting -- fake
- * an interrupt to make sure we process any existing
- * state
- */
- smsm_irq_handler(0, 0);
-
SMD_INFO("smd_core_init() done\n");
return 0;
}
+static int intr_init(struct interrupt_config_item *private_irq,
+ struct smd_irq_config *platform_irq,
+ struct platform_device *pdev
+ )
+{
+ int irq_id;
+ int ret;
+ int ret_wake;
+
+ private_irq->out_bit_pos = platform_irq->out_bit_pos;
+ private_irq->out_offset = platform_irq->out_offset;
+ private_irq->out_base = platform_irq->out_base;
+
+ irq_id = platform_get_irq_byname(
+ pdev,
+ platform_irq->irq_name
+ );
+ SMD_DBG("smd: %s: register irq: %s id: %d\n", __func__,
+ platform_irq->irq_name, irq_id);
+ ret = request_irq(irq_id,
+ private_irq->irq_handler,
+ platform_irq->flags,
+ platform_irq->device_name,
+ (void *)platform_irq->dev_id
+ );
+ if (ret < 0) {
+ platform_irq->irq_id = ret;
+ } else {
+ platform_irq->irq_id = irq_id;
+ ret_wake = enable_irq_wake(irq_id);
+ if (ret_wake < 0) {
+ pr_err("smd: enable_irq_wake failed on %s",
+ platform_irq->irq_name);
+ }
+ }
+
+ return ret;
+}
+
+int smd_core_platform_init(struct platform_device *pdev)
+{
+ int i;
+ int ret;
+ uint32_t num_ss;
+ struct smd_platform *smd_platform_data;
+ struct smd_subsystem_config *smd_ss_config_list;
+ struct smd_subsystem_config *cfg;
+ int err_ret = 0;
+
+ smd_platform_data = pdev->dev.platform_data;
+ num_ss = smd_platform_data->num_ss_configs;
+ smd_ss_config_list = smd_platform_data->smd_ss_configs;
+
+ for (i = 0; i < num_ss; i++) {
+ cfg = &smd_ss_config_list[i];
+
+ ret = intr_init(
+ &private_intr_config[cfg->irq_config_id].smd,
+ &cfg->smd_int,
+ pdev
+ );
+
+ if (ret < 0) {
+ err_ret = ret;
+ pr_err("smd: register irq failed on %s\n",
+ cfg->smd_int.irq_name);
+ break;
+ }
+
+ ret = intr_init(
+ &private_intr_config[cfg->irq_config_id].smsm,
+ &cfg->smsm_int,
+ pdev
+ );
+
+ if (ret < 0) {
+ err_ret = ret;
+ pr_err("smd: register irq failed on %s\n",
+ cfg->smsm_int.irq_name);
+ break;
+ }
+ }
+
+ if (err_ret < 0) {
+ pr_err("smd: deregistering IRQs\n");
+ for (i = 0; i < num_ss; ++i) {
+ cfg = &smd_ss_config_list[i];
+
+ if (cfg->smd_int.irq_id >= 0)
+ free_irq(cfg->smd_int.irq_id,
+ (void *)cfg->smd_int.dev_id
+ );
+ if (cfg->smsm_int.irq_id >= 0)
+ free_irq(cfg->smsm_int.irq_id,
+ (void *)cfg->smsm_int.dev_id
+ );
+ }
+ return err_ret;
+ }
+
+ SMD_INFO("smd_core_platform_init() done\n");
+ return 0;
+
+}
+
static int __devinit msm_smd_probe(struct platform_device *pdev)
{
- SMD_INFO("smd probe\n");
+ int ret;
+ SMD_INFO("smd probe\n");
INIT_WORK(&probe_work, smd_channel_probe_worker);
channel_close_wq = create_singlethread_workqueue("smd_channel_close");
@@ -2596,9 +2780,27 @@
return -1;
}
- if (smd_core_init()) {
- pr_err("smd_core_init() failed\n");
- return -1;
+ if (pdev) {
+ if (pdev->dev.of_node) {
+ pr_err("SMD: Device tree not currently supported\n");
+ return -ENODEV;
+ } else if (pdev->dev.platform_data) {
+ ret = smd_core_platform_init(pdev);
+ if (ret) {
+ pr_err(
+ "SMD: smd_core_platform_init() failed\n");
+ return -ENODEV;
+ }
+ } else {
+ ret = smd_core_init();
+ if (ret) {
+ pr_err("smd_core_init() failed\n");
+ return -ENODEV;
+ }
+ }
+ } else {
+ pr_err("SMD: PDEV not found\n");
+ return -ENODEV;
}
smd_initialized = 1;
@@ -2619,7 +2821,7 @@
{SMD_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
{SMD_WCNSS, "riva", .nb.notifier_call = restart_notifier_cb},
{SMD_DSPS, "dsps", .nb.notifier_call = restart_notifier_cb},
- {SMD_MODEM, "gnss", .nb.notifier_call = restart_notifier_cb},
+ {SMD_MODEM, "gss", .nb.notifier_call = restart_notifier_cb},
};
static int restart_notifier_cb(struct notifier_block *this,
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 8023129..63c5fef 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -31,6 +31,7 @@
#include <linux/msm_smd_pkt.h>
#include <linux/poll.h>
#include <asm/ioctls.h>
+#include <linux/wakelock.h>
#include <mach/msm_smd.h>
#include <mach/peripheral-loader.h>
@@ -45,6 +46,7 @@
#define LOOPBACK_INX (NUM_SMD_PKT_PORTS - 1)
#define DEVICE_NAME "smdpkt"
+#define WAKELOCK_TIMEOUT (2*HZ)
struct smd_pkt_dev {
struct cdev cdev;
@@ -70,7 +72,8 @@
int has_reset;
int do_reset_notification;
struct completion ch_allocated;
-
+ struct wake_lock pa_wake_lock; /* Packet Arrival Wake lock*/
+ struct work_struct packet_arrival_work;
} *smd_pkt_devp[NUM_SMD_PKT_PORTS];
struct class *smd_pkt_classp;
@@ -183,6 +186,19 @@
}
+static void packet_arrival_worker(struct work_struct *work)
+{
+ struct smd_pkt_dev *smd_pkt_devp;
+
+ smd_pkt_devp = container_of(work, struct smd_pkt_dev,
+ packet_arrival_work);
+ mutex_lock(&smd_pkt_devp->ch_lock);
+ if (smd_pkt_devp->ch)
+ wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
+ WAKELOCK_TIMEOUT);
+ mutex_unlock(&smd_pkt_devp->ch_lock);
+}
+
static long smd_pkt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -421,6 +437,7 @@
/* here we have a packet of size sz ready */
wake_up(&smd_pkt_devp->ch_read_wait_queue);
+ schedule_work(&smd_pkt_devp->packet_arrival_work);
D(KERN_ERR "%s: after wake_up\n", __func__);
}
@@ -579,6 +596,10 @@
if (!smd_pkt_devp)
return -EINVAL;
+ wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
+ smd_pkt_dev_name[smd_pkt_devp->i]);
+ INIT_WORK(&smd_pkt_devp->packet_arrival_work, packet_arrival_worker);
+
file->private_data = smd_pkt_devp;
mutex_lock(&smd_pkt_devp->ch_lock);
@@ -665,6 +686,9 @@
out:
mutex_unlock(&smd_pkt_devp->ch_lock);
+ if (r < 0)
+ wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
+
return r;
}
@@ -690,6 +714,7 @@
smd_pkt_devp->has_reset = 0;
smd_pkt_devp->do_reset_notification = 0;
+ wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
return r;
}
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 021a216..4a7cf91 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -18,7 +18,6 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <mach/msm_iomap.h>
-#include <mach/socinfo.h>
#include "spm_driver.h"
@@ -128,10 +127,6 @@
{
uint32_t value = enable ? 0x01 : 0x00;
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
if (!dev)
return -EINVAL;
@@ -150,10 +145,6 @@
int i;
int num_spm_entry = msm_spm_drv_get_num_spm_entry(dev);
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return;
-
if (!dev) {
__WARN();
return;
@@ -174,10 +165,6 @@
uint32_t offset_w = offset / 4;
int ret = 0;
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
if (!cmd || !dev) {
__WARN();
goto failed_write_seq_data;
@@ -214,10 +201,6 @@
uint32_t addr)
{
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
/* SPM is configured to reset start address to zero after end of Program
*/
if (!dev)
@@ -242,10 +225,6 @@
{
uint32_t timeout_us;
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
if (!dev)
return -EINVAL;
@@ -299,10 +278,6 @@
int i;
int num_spm_entry;
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
BUG_ON(!dev || !data);
dev->reg_base_addr = data->reg_base_addr;
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 0aa1358..883dec1 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -19,7 +19,6 @@
#include <linux/slab.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
-
#include "spm.h"
#include "spm_driver.h"
@@ -130,11 +129,6 @@
int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
{
struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
-
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
return msm_spm_dev_set_low_power_mode(dev, mode, notify_rpm);
}
@@ -143,10 +137,6 @@
unsigned int cpu;
int ret = 0;
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
BUG_ON((nr_devs < num_possible_cpus()) || !data);
for_each_possible_cpu(cpu) {
@@ -210,10 +200,6 @@
int __init msm_spm_l2_init(struct msm_spm_platform_data *data)
{
- /* TODO: Remove this after 8064 bring up */
- if (cpu_is_apq8064())
- return 0;
-
return msm_spm_dev_init(&msm_spm_l2_device, data);
}
#endif
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 3d44075..4128e3a 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -215,13 +215,13 @@
return __raw_readl(addr);
t1 = __raw_readl(addr);
- t2 = __raw_readl(addr);
+ t2 = __raw_readl_no_log(addr);
if ((t2-t1) <= 1)
return t2;
while (1) {
- t1 = __raw_readl(addr);
- t2 = __raw_readl(addr);
- t3 = __raw_readl(addr);
+ t1 = __raw_readl_no_log(addr);
+ t2 = __raw_readl_no_log(addr);
+ t3 = __raw_readl_no_log(addr);
cpu_relax();
if ((t3-t2) <= 1)
return t3;
@@ -304,7 +304,7 @@
/* read the counter four extra times to make sure write posts
before reading the time */
for (i = 0; i < 4; i++)
- __raw_readl(clock->regbase + TIMER_COUNT_VAL);
+ __raw_readl_no_log(clock->regbase + TIMER_COUNT_VAL);
}
now = msm_read_timer_count(clock, LOCAL_TIMER);
clock_state->last_set = now;
@@ -415,11 +415,12 @@
tmp /= (loop_zero_count-1);
while (loop_zero_count--) {
- t1 = __raw_readl(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+ t1 = __raw_readl_no_log(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
do {
udelay(1);
t2 = t1;
- t1 = __raw_readl(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+ t1 = __raw_readl_no_log(
+ MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
} while ((t2 != t1) && --loop_count);
if (!loop_count) {
@@ -1087,7 +1088,8 @@
res = request_percpu_irq(ce->irq, msm_timer_interrupt,
ce->name, clock->percpu_evt);
if (!res)
- enable_percpu_irq(ce->irq, 0);
+ enable_percpu_irq(ce->irq,
+ IRQ_TYPE_EDGE_RISING);
} else {
clock->evt = ce;
res = request_irq(ce->irq, msm_timer_interrupt,
@@ -1150,7 +1152,7 @@
*__this_cpu_ptr(clock->percpu_evt) = evt;
clockevents_register_device(evt);
- enable_percpu_irq(evt->irq, 0);
+ enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
return 0;
}
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 5cd1b05..3bce534 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -54,9 +54,15 @@
and r1, r1, #7 @ mask of the bits for current cache only
cmp r1, #2 @ see what cache we have at this level
blt skip @ skip if no cache, or just i-cache
+#ifdef CONFIG_PREEMPT
+ save_and_disable_irqs r9 @ make cssr&csidr read atomic
+#endif
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
isb @ isb to sych the new cssr&csidr
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+#ifdef CONFIG_PREEMPT
+ restore_irqs_notrace r9
+#endif
and r2, r1, #7 @ extract the length of the cache lines
add r2, r2, #4 @ add 4 (line length offset)
ldr r4, =0x3ff
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index b4ca325..7d2e44f 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,3 +1136,4 @@
apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
+msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 7ceae89..07322cd 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -124,7 +124,8 @@
*/
int chk_apps_master(void)
{
- if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615())
+ if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
+ cpu_is_apq8064() || cpu_is_msm8627())
return 1;
else
return 0;
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index f2a2210..df2cd65 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -86,8 +86,8 @@
diagchar_ioctl(NULL, DIAG_IOCTL_COMMAND_REG,
(unsigned long)pkt_params);
kfree(temp);
- buf = buf + HDR_SIZ + data_len;
}
+ buf = buf + HDR_SIZ + data_len;
}
}
kfree(pkt_params);
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index b03a4ec..f5367ef 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -242,6 +242,9 @@
static int __init msm_rng_init(void)
{
+ if (cpu_is_apq8064())
+ return -ENODEV;
+
return platform_driver_register(&rng_driver);
}
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index fc1cfb6..a6b0cf6 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -27,9 +27,11 @@
#include <linux/memory_alloc.h>
#include <linux/seq_file.h>
#include <linux/fmem.h>
+#include <linux/iommu.h>
#include <mach/msm_memtypes.h>
#include <mach/scm.h>
-#include "ion_priv.h"
+#include <mach/iommu_domains.h>
+ #include "ion_priv.h"
#include <asm/mach/map.h>
@@ -566,6 +568,103 @@
return ret_value;
}
+static int ion_cp_heap_map_iommu(struct ion_buffer *buffer,
+ struct ion_iommu_map *data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags)
+{
+ unsigned long temp_phys, temp_iova;
+ struct iommu_domain *domain;
+ int i, ret = 0;
+ unsigned long extra;
+
+ data->mapped_size = iova_length;
+
+ if (!msm_use_iommu()) {
+ data->iova_addr = buffer->priv_phys;
+ return 0;
+ }
+
+ extra = iova_length - buffer->size;
+
+ data->iova_addr = msm_allocate_iova_address(domain_num, partition_num,
+ data->mapped_size, align);
+
+ if (!data->iova_addr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ temp_iova = data->iova_addr;
+ temp_phys = buffer->priv_phys;
+ for (i = buffer->size; i > 0; i -= SZ_4K, temp_iova += SZ_4K,
+ temp_phys += SZ_4K) {
+ ret = iommu_map(domain, temp_iova, temp_phys,
+ get_order(SZ_4K),
+ ION_IS_CACHED(flags) ? 1 : 0);
+
+ if (ret) {
+ pr_err("%s: could not map %lx to %lx in domain %p\n",
+ __func__, temp_iova, temp_phys, domain);
+ goto out2;
+ }
+ }
+
+ if (extra && (msm_iommu_map_extra(domain, temp_iova, extra, flags) < 0))
+ goto out2;
+
+ return 0;
+
+out2:
+ for ( ; i < buffer->size; i += SZ_4K, temp_iova -= SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+out1:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+out:
+ return ret;
+}
+
+static void ion_cp_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+ int i;
+ unsigned long temp_iova;
+ unsigned int domain_num;
+ unsigned int partition_num;
+ struct iommu_domain *domain;
+
+ if (!msm_use_iommu())
+ return;
+
+ domain_num = iommu_map_domain(data);
+ partition_num = iommu_map_partition(data);
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ temp_iova = data->iova_addr;
+ for (i = data->mapped_size; i > 0; i -= SZ_4K, temp_iova += SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+
+ return;
+}
static struct ion_heap_ops cp_heap_ops = {
.allocate = ion_cp_heap_allocate,
@@ -581,6 +680,8 @@
.print_debug = ion_cp_print_debug,
.secure_heap = ion_cp_secure_heap,
.unsecure_heap = ion_cp_unsecure_heap,
+ .map_iommu = ion_cp_heap_map_iommu,
+ .unmap_iommu = ion_cp_heap_unmap_iommu,
};
struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 805e2b6..bde4045 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -131,31 +131,35 @@
struct adreno_gpudev *gpudev;
unsigned int istore_size;
unsigned int pix_shader_start;
+ unsigned int instruction_size; /* Size of an instruction in dwords */
} adreno_gpulist[] = {
{ ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID,
"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
- 512, 384},
+ 512, 384, 3},
{ ADRENO_REV_A205, 0, 1, 0, ANY_ID,
"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
- 512, 384},
+ 512, 384, 3},
{ ADRENO_REV_A220, 2, 1, ANY_ID, ANY_ID,
"leia_pm4_470.fw", "leia_pfp_470.fw", &adreno_a2xx_gpudev,
- 512, 384},
+ 512, 384, 3},
/*
* patchlevel 5 (8960v2) needs special pm4 firmware to work around
* a hardware problem.
*/
{ ADRENO_REV_A225, 2, 2, 0, 5,
"a225p5_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
- 1536, 768 },
+ 1536, 768, 3 },
{ ADRENO_REV_A225, 2, 2, 0, 6,
"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
- 1536, 768 },
+ 1536, 768, 3 },
{ ADRENO_REV_A225, 2, 2, ANY_ID, ANY_ID,
"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
- 1536, 768 },
+ 1536, 768, 3 },
+ /* A3XX doesn't use the pix_shader_start */
{ ADRENO_REV_A320, 3, 1, ANY_ID, ANY_ID,
- "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev },
+ "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
+ 512, 0, 2 },
+
};
static irqreturn_t adreno_isr(int irq, void *data)
@@ -248,6 +252,16 @@
unsigned int mh_mmu_invalidate = 0x00000003; /*invalidate all and tc */
/*
+ * A3XX doesn't support the fast path (the registers don't even exist)
+ * so just bail out early
+ */
+
+ if (adreno_is_a3xx(adreno_dev)) {
+ kgsl_mmu_device_setstate(device, flags);
+ return;
+ }
+
+ /*
* If possible, then set the state via the command stream to avoid
* a CPU idle. Otherwise, use the default setstate which uses register
* writes For CFF dump we must idle and use the registers so that it is
@@ -442,6 +456,7 @@
adreno_dev->pm4_fwfile = adreno_gpulist[i].pm4fw;
adreno_dev->istore_size = adreno_gpulist[i].istore_size;
adreno_dev->pix_shader_start = adreno_gpulist[i].pix_shader_start;
+ adreno_dev->instruction_size = adreno_gpulist[i].instruction_size;
}
static int __devinit
@@ -819,7 +834,11 @@
unsigned int rbbm_status;
unsigned long wait_timeout =
msecs_to_jiffies(adreno_dev->wait_timeout);
- unsigned long wait_time = jiffies + wait_timeout;
+ unsigned long wait_time;
+ unsigned long wait_time_part;
+ unsigned int msecs;
+ unsigned int msecs_first;
+ unsigned int msecs_part;
kgsl_cffdump_regpoll(device->id,
adreno_dev->gpudev->reg_rbbm_status << 2,
@@ -829,8 +848,18 @@
*/
retry:
if (rb->flags & KGSL_FLAGS_STARTED) {
+ msecs = adreno_dev->wait_timeout;
+ msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
+ msecs_part = (msecs - msecs_first + 3) / 4;
+ wait_time = jiffies + wait_timeout;
+ wait_time_part = jiffies + msecs_to_jiffies(msecs_first);
adreno_poke(device);
do {
+ if (time_after(jiffies, wait_time_part)) {
+ adreno_poke(device);
+ wait_time_part = jiffies +
+ msecs_to_jiffies(msecs_part);
+ }
GSL_RB_GET_READPTR(rb, &rb->rptr);
if (time_after(jiffies, wait_time)) {
KGSL_DRV_ERR(device, "rptr: %x, wptr: %x\n",
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9c2d704..9498b80 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -39,12 +39,7 @@
#define ADRENO_DEFAULT_PWRSCALE_POLICY NULL
#endif
-/*
- * constants for the size of shader instructions
- */
-#define ADRENO_ISTORE_BYTES 12
-#define ADRENO_ISTORE_WORDS 3
-#define ADRENO_ISTORE_START 0x5000
+#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
enum adreno_gpurev {
ADRENO_REV_UNKNOWN = 0,
@@ -75,6 +70,7 @@
unsigned int wait_timeout;
unsigned int istore_size;
unsigned int pix_shader_start;
+ unsigned int instruction_size;
};
struct adreno_gpudev {
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index e31b76b..f2b1278 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -164,7 +164,8 @@
static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
{
- return adreno_dev->istore_size*ADRENO_ISTORE_BYTES;
+ return adreno_dev->istore_size *
+ (adreno_dev->instruction_size * sizeof(unsigned int));
}
static inline int _context_size(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 1bad811..f68bc41 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -34,7 +34,7 @@
0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
- 0x0579, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
+ 0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
@@ -127,13 +127,8 @@
#define HLSQ_MEMOBJ_OFFSET 0x400
#define HLSQ_MIPMAP_OFFSET 0x800
-#ifdef GSL_USE_A3XX_HLSQ_SHADOW_RAM
/* Use shadow RAM */
#define HLSQ_SHADOW_BASE (0x10000+SSIZE*2)
-#else
-/* Use working RAM */
-#define HLSQ_SHADOW_BASE 0x10000
-#endif
#define REG_TO_MEM_LOOP_COUNT_SHIFT 15
@@ -258,7 +253,7 @@
struct adreno_context *drawctxt)
{
unsigned int *cmd = tmp_ctx.cmd;
- unsigned int *start = cmd;
+ unsigned int *start;
unsigned int i;
drawctxt->constant_save_commands[0].hostptr = cmd;
@@ -266,6 +261,8 @@
virt2gpu(cmd, &drawctxt->gpustate);
cmd++;
+ start = cmd;
+
*cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
*cmd++ = 0;
@@ -1313,7 +1310,8 @@
_SET(SP_FSCTRLREG1_FSINITIALOUTSTANDING, 2) |
_SET(SP_FSCTRLREG1_HALFPRECVAROFFSET, 63);
/* SP_FS_OBJ_OFFSET_REG */
- *cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128);
+ *cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128) |
+ _SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 1);
/* SP_FS_OBJ_START_REG */
*cmds++ = 0x00000000;
@@ -1329,7 +1327,7 @@
/* SP_FS_OUT_REG */
*cmds++ = _SET(SP_FSOUTREG_PAD0, SP_PIXEL_BASED);
- *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
*cmds++ = CP_REG(A3XX_SP_FS_MRT_REG_0);
/* SP_FS_MRT_REG0 */
*cmds++ = _SET(SP_FSMRTREG_REGID, 4);
@@ -1426,7 +1424,7 @@
_SET(VPC_VPCVARPSREPLMODE_COMPONENT16, 1) |
_SET(VPC_VPCVARPSREPLMODE_COMPONENT17, 2);
- *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 11);
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_SP_SP_CTRL_REG);
/* SP_SP_CTRL_REG */
*cmds++ = _SET(SP_SPCTRLREG_SLEEPMODE, 1);
@@ -1652,7 +1650,9 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_GRAS_SC_CONTROL);
/* GRAS_SC_CONTROL */
- *cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1);
+ /*cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1);
+ *cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1) |*/
+ *cmds++ = 0x04001000;
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_GRAS_SU_MODE_CONTROL);
@@ -2130,24 +2130,17 @@
static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt)
{
+ int result;
+
calc_gmemsize(&drawctxt->context_gmem_shadow,
adreno_dev->gmemspace.sizebytes);
tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
- if (drawctxt->flags & CTXT_FLAGS_GMEM_SHADOW) {
- int result =
- kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
- drawctxt->pagetable,
- drawctxt->context_gmem_shadow.size);
+ result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
+ drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
- if (result)
- return result;
- } else {
- memset(&drawctxt->context_gmem_shadow.gmemshadow, 0,
- sizeof(drawctxt->context_gmem_shadow.gmemshadow));
-
- return 0;
- }
+ if (result)
+ return result;
build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
&tmp_ctx.cmd);
@@ -2163,6 +2156,8 @@
kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
KGSL_CACHE_OP_FLUSH);
+ drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
+
return 0;
}
@@ -2431,10 +2426,7 @@
#define A3XX_INT_MASK \
((1 << A3XX_INT_RBBM_AHB_ERROR) | \
(1 << A3XX_INT_RBBM_REG_TIMEOUT) | \
- (1 << A3XX_INT_RBBM_ME_MS_TIMEOUT) | \
- (1 << A3XX_INT_RBBM_PFP_MS_TIMEOUT) | \
(1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW) | \
- (1 << A3XX_INT_VFD_ERROR) | \
(1 << A3XX_INT_CP_T0_PACKET_IN_IB) | \
(1 << A3XX_INT_CP_OPCODE_ERROR) | \
(1 << A3XX_INT_CP_RESERVED_BIT_ERROR) | \
@@ -2444,7 +2436,6 @@
(1 << A3XX_INT_CP_RB_INT) | \
(1 << A3XX_INT_CP_REG_PROTECT_FAULT) | \
(1 << A3XX_INT_CP_AHB_ERROR_HALT) | \
- (1 << A3XX_INT_MISC_HANG_DETECT) | \
(1 << A3XX_INT_UCHE_OOB_ACCESS))
static struct {
@@ -2474,7 +2465,7 @@
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 21 - CP_AHB_ERROR_FAULT */
A3XX_IRQ_CALLBACK(NULL), /* 22 - Unused */
A3XX_IRQ_CALLBACK(NULL), /* 23 - Unused */
- A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 24 - MISC_HANG_DETECT */
+ A3XX_IRQ_CALLBACK(NULL), /* 24 - MISC_HANG_DETECT */
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 25 - UCHE_OOB_ACCESS */
/* 26 to 31 - Unused */
};
@@ -2547,6 +2538,9 @@
{
struct kgsl_device *device = &adreno_dev->dev;
+ /* GMEM size on A320 is 512K */
+ adreno_dev->gmemspace.sizebytes = SZ_512K;
+
/* Reset the core */
adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD,
0x00000001);
@@ -2570,10 +2564,17 @@
adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
/* Enable AHB error reporting */
- adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
+ adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0x86FFFFFF);
/* Turn on the power counters */
adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00003000);
+
+ /* Turn on hang detection - this spews a lot of useful information
+ * into the RBBM registers on a hang */
+
+ adreno_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
+ (1 << 16) | 0xFFF);
+
}
/* Defined in adreno_a3xx_snapshot.c */
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index aade50c..c8c7c441 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -80,7 +80,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_snapshot_debug *header = snapshot;
unsigned int *data = snapshot + sizeof(*header);
- int i, size = adreno_dev->pm4_fw_size >> 2;
+ int i, size = adreno_dev->pm4_fw_size - 1;
if (remain < DEBUG_SECTION_SZ(size)) {
SNAPSHOT_ERR_NOMEM(device, "CP PM4 RAM DEBUG");
@@ -98,7 +98,7 @@
*/
adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
- for (i = 0; i < adreno_dev->pm4_fw_size >> 2; i++)
+ for (i = 0; i < size; i++)
adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
return DEBUG_SECTION_SZ(size);
@@ -110,7 +110,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_snapshot_debug *header = snapshot;
unsigned int *data = snapshot + sizeof(*header);
- int i, size = adreno_dev->pfp_fw_size >> 2;
+ int i, size = adreno_dev->pfp_fw_size - 1;
if (remain < DEBUG_SECTION_SZ(size)) {
SNAPSHOT_ERR_NOMEM(device, "CP PFP RAM DEBUG");
@@ -127,7 +127,7 @@
* maintain always changing hardcoded constants
*/
kgsl_regwrite(device, A3XX_CP_PFP_UCODE_ADDR, 0x0);
- for (i = 0; i < adreno_dev->pfp_fw_size >> 2; i++)
+ for (i = 0; i < size; i++)
adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
return DEBUG_SECTION_SZ(size);
@@ -175,7 +175,7 @@
return 0;
}
- val = (id << 0x06) | (1 << 0x10);
+ val = (id << 8) | (1 << 16);
header->id = id;
header->count = DEBUGFS_BLOCK_SIZE;
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index c1b9e4c..b53ca8f 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -143,7 +143,8 @@
return 0;
adreno_dev = ADRENO_DEVICE(device);
- count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
+ count = adreno_dev->istore_size * adreno_dev->instruction_size;
+
remaining = count;
for (i = 0; i < count; i += rowc) {
unsigned int vals[rowc];
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 9bf85cf..aeb89b3 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -86,7 +86,7 @@
gmem_restore_quad[7] = uint2float(shadow->width);
memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2);
- memcpy(shadow->quad_vertices_restore.hostptr, gmem_copy_quad,
+ memcpy(shadow->quad_vertices_restore.hostptr, gmem_restore_quad,
QUAD_RESTORE_LEN << 2);
memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index fb88a72..cc3f3e7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -86,7 +86,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int count, i;
- count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
+ count = adreno_dev->istore_size * adreno_dev->instruction_size;
if (remain < (count * 4) + sizeof(*header)) {
KGSL_DRV_ERR(device,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 1b6696b..512a262 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2231,6 +2231,7 @@
int kgsl_device_platform_probe(struct kgsl_device *device,
irqreturn_t (*dev_isr) (int, void*))
{
+ int result;
int status = -EINVAL;
struct kgsl_memregion *regspace = NULL;
struct resource *res;
@@ -2291,6 +2292,9 @@
device->id, regspace->mmio_phys_base,
regspace->sizebytes, regspace->mmio_virt_base);
+ result = kgsl_drm_init(pdev);
+ if (result)
+ goto error_iounmap;
status = kgsl_register_device(device);
if (!status)
@@ -2426,11 +2430,6 @@
goto err;
}
- result = kgsl_drm_init(NULL);
-
- if (result)
- goto err;
-
return 0;
err:
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index dba2dfc..e3f6f3b 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,6 @@
#include "drmP.h"
#include "drm.h"
#include <linux/android_pmem.h>
-#include <linux/notifier.h>
#include "kgsl.h"
#include "kgsl_device.h"
@@ -39,6 +38,9 @@
#define ENTRY_EMPTY -1
#define ENTRY_NEEDS_CLEANUP -2
+#define DRM_KGSL_NOT_INITED -1
+#define DRM_KGSL_INITED 1
+
#define DRM_KGSL_NUM_FENCE_ENTRIES (DRM_KGSL_HANDLE_WAIT_ENTRIES << 2)
#define DRM_KGSL_HANDLE_WAIT_ENTRIES 5
@@ -127,6 +129,8 @@
struct list_head wait_list;
};
+static int kgsl_drm_inited = DRM_KGSL_NOT_INITED;
+
/* This is a global list of all the memory currently mapped in the MMU */
static struct list_head kgsl_mem_list;
@@ -186,41 +190,6 @@
struct kgsl_device_private *devpriv[KGSL_DEVICE_MAX];
};
-static int kgsl_ts_notifier_cb(struct notifier_block *blk,
- unsigned long code, void *_param);
-
-static struct notifier_block kgsl_ts_nb[KGSL_DEVICE_MAX];
-
-static int kgsl_drm_firstopen(struct drm_device *dev)
-{
- int i;
-
- for (i = 0; i < KGSL_DEVICE_MAX; i++) {
- struct kgsl_device *device = kgsl_get_device(i);
-
- if (device == NULL)
- continue;
-
- kgsl_ts_nb[i].notifier_call = kgsl_ts_notifier_cb;
- kgsl_register_ts_notifier(device, &kgsl_ts_nb[i]);
- }
-
- return 0;
-}
-
-void kgsl_drm_lastclose(struct drm_device *dev)
-{
- int i;
-
- for (i = 0; i < KGSL_DEVICE_MAX; i++) {
- struct kgsl_device *device = kgsl_get_device(i);
- if (device == NULL)
- continue;
-
- kgsl_unregister_ts_notifier(device, &kgsl_ts_nb[i]);
- }
-}
-
void kgsl_drm_preclose(struct drm_device *dev, struct drm_file *file_priv)
{
}
@@ -268,74 +237,72 @@
{
struct drm_kgsl_gem_object *priv = obj->driver_private;
int index;
+ int result = 0;
/* Return if the memory is already allocated */
if (kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
return 0;
+ if (priv->pagetable == NULL) {
+ priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+
+ if (priv->pagetable == NULL) {
+ DRM_ERROR("Unable to get the GPU MMU pagetable\n");
+ return -EINVAL;
+ }
+ }
+
if (TYPE_IS_PMEM(priv->type)) {
int type;
if (priv->type == DRM_KGSL_GEM_TYPE_EBI ||
- priv->type & DRM_KGSL_GEM_PMEM_EBI)
- type = PMEM_MEMTYPE_EBI1;
- else
- type = PMEM_MEMTYPE_SMI;
-
- priv->memdesc.physaddr =
- pmem_kalloc(obj->size * priv->bufcount,
- type | PMEM_ALIGNMENT_4K);
-
- if (IS_ERR((void *) priv->memdesc.physaddr)) {
- DRM_ERROR("Unable to allocate PMEM memory\n");
- return -ENOMEM;
+ priv->type & DRM_KGSL_GEM_PMEM_EBI) {
+ type = PMEM_MEMTYPE_EBI1;
+ result = kgsl_sharedmem_ebimem_user(
+ &priv->memdesc,
+ priv->pagetable,
+ obj->size * priv->bufcount,
+ 0);
+ if (result) {
+ DRM_ERROR(
+ "Unable to allocate PMEM memory\n");
+ return result;
+ }
}
-
- priv->memdesc.size = obj->size * priv->bufcount;
+ else
+ return -EINVAL;
} else if (TYPE_IS_MEM(priv->type)) {
- priv->memdesc.hostptr =
- vmalloc_user(obj->size * priv->bufcount);
- if (priv->memdesc.hostptr == NULL) {
- DRM_ERROR("Unable to allocate vmalloc memory\n");
- return -ENOMEM;
+ if (priv->type == DRM_KGSL_GEM_TYPE_KMEM ||
+ priv->type & DRM_KGSL_GEM_CACHE_MASK)
+ list_add(&priv->list, &kgsl_mem_list);
+
+ result = kgsl_sharedmem_vmalloc_user(&priv->memdesc,
+ priv->pagetable,
+ obj->size * priv->bufcount, 0);
+
+ if (result != 0) {
+ DRM_ERROR(
+ "Unable to allocate Vmalloc user memory\n");
+ return result;
}
-
- priv->memdesc.size = obj->size * priv->bufcount;
- priv->memdesc.ops = &kgsl_vmalloc_ops;
} else
return -EINVAL;
- for (index = 0; index < priv->bufcount; index++)
+ for (index = 0; index < priv->bufcount; index++) {
priv->bufs[index].offset = index * obj->size;
-
+ priv->bufs[index].gpuaddr =
+ priv->memdesc.gpuaddr +
+ priv->bufs[index].offset;
+ }
+ priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
return 0;
}
static void
-kgsl_gem_unmap(struct drm_gem_object *obj)
-{
- struct drm_kgsl_gem_object *priv = obj->driver_private;
-
- if (!priv->flags & DRM_KGSL_GEM_FLAG_MAPPED)
- return;
-
- kgsl_mmu_unmap(priv->pagetable, &priv->memdesc);
-
- kgsl_mmu_putpagetable(priv->pagetable);
- priv->pagetable = NULL;
-
- if ((priv->type == DRM_KGSL_GEM_TYPE_KMEM) ||
- (priv->type & DRM_KGSL_GEM_CACHE_MASK))
- list_del(&priv->list);
-
- priv->flags &= ~DRM_KGSL_GEM_FLAG_MAPPED;
-}
-
-static void
kgsl_gem_free_memory(struct drm_gem_object *obj)
{
struct drm_kgsl_gem_object *priv = obj->driver_private;
@@ -346,12 +313,17 @@
kgsl_gem_mem_flush(&priv->memdesc, priv->type,
DRM_KGSL_GEM_CACHE_OP_FROM_DEV);
- kgsl_gem_unmap(obj);
-
- if (TYPE_IS_PMEM(priv->type))
- pmem_kfree(priv->memdesc.physaddr);
-
kgsl_sharedmem_free(&priv->memdesc);
+
+ kgsl_mmu_putpagetable(priv->pagetable);
+ priv->pagetable = NULL;
+
+ if ((priv->type == DRM_KGSL_GEM_TYPE_KMEM) ||
+ (priv->type & DRM_KGSL_GEM_CACHE_MASK))
+ list_del(&priv->list);
+
+ priv->flags &= ~DRM_KGSL_GEM_FLAG_MAPPED;
+
}
int
@@ -447,7 +419,7 @@
filp = fget(drm_fd);
if (unlikely(filp == NULL)) {
- DRM_ERROR("Unable to ghet the DRM file descriptor\n");
+ DRM_ERROR("Unable to get the DRM file descriptor\n");
return -EINVAL;
}
file_priv = filp->private_data;
@@ -520,7 +492,7 @@
ret = drm_gem_handle_create(file_priv, obj, handle);
- drm_gem_object_handle_unreference(obj);
+ drm_gem_object_unreference(obj);
INIT_LIST_HEAD(&priv->wait_list);
for (i = 0; i < DRM_KGSL_HANDLE_WAIT_ENTRIES; i++) {
@@ -695,109 +667,14 @@
kgsl_gem_unbind_gpu_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_kgsl_gem_bind_gpu *args = data;
- struct drm_gem_object *obj;
- struct drm_kgsl_gem_object *priv;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-
- if (obj == NULL) {
- DRM_ERROR("Invalid GEM handle %x\n", args->handle);
- return -EBADF;
- }
-
- mutex_lock(&dev->struct_mutex);
- priv = obj->driver_private;
-
- if (--priv->bound == 0)
- kgsl_gem_unmap(obj);
-
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
return 0;
}
-static int
-kgsl_gem_map(struct drm_gem_object *obj)
-{
- struct drm_kgsl_gem_object *priv = obj->driver_private;
- int index;
- int ret = -EINVAL;
-
- if (priv->flags & DRM_KGSL_GEM_FLAG_MAPPED)
- return 0;
-
- /* Get the global page table */
-
- if (priv->pagetable == NULL) {
- priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
-
- if (priv->pagetable == NULL) {
- DRM_ERROR("Unable to get the GPU MMU pagetable\n");
- return -EINVAL;
- }
- }
-
- priv->memdesc.pagetable = priv->pagetable;
-
- ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
-
- if (!ret) {
- for (index = 0; index < priv->bufcount; index++) {
- priv->bufs[index].gpuaddr =
- priv->memdesc.gpuaddr +
- priv->bufs[index].offset;
- }
- }
-
- /* Add cached memory to the list to be cached */
-
- if (priv->type == DRM_KGSL_GEM_TYPE_KMEM ||
- priv->type & DRM_KGSL_GEM_CACHE_MASK)
- list_add(&priv->list, &kgsl_mem_list);
-
- priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
-
- return ret;
-}
-
int
kgsl_gem_bind_gpu_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- struct drm_kgsl_gem_bind_gpu *args = data;
- struct drm_gem_object *obj;
- struct drm_kgsl_gem_object *priv;
- int ret = 0;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-
- if (obj == NULL) {
- DRM_ERROR("Invalid GEM handle %x\n", args->handle);
- return -EBADF;
- }
-
- mutex_lock(&dev->struct_mutex);
- priv = obj->driver_private;
-
- if (priv->bound++ == 0) {
-
- if (!kgsl_gem_memory_allocated(obj)) {
- DRM_ERROR("Memory not allocated for this object\n");
- ret = -ENOMEM;
- goto out;
- }
-
- ret = kgsl_gem_map(obj);
-
- /* This is legacy behavior - use GET_BUFFERINFO instead */
- args->gpuptr = priv->bufs[0].gpuaddr;
- }
-out:
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
+ return 0;
}
/* Allocate the memory and prepare it for CPU mapping */
@@ -1344,27 +1221,6 @@
fence->fence_id = ENTRY_NEEDS_CLEANUP; /* Mark it as needing cleanup */
}
-static int kgsl_ts_notifier_cb(struct notifier_block *blk,
- unsigned long code, void *_param)
-{
- struct drm_kgsl_gem_object_fence *fence;
- struct kgsl_device *device = kgsl_get_device(code);
- int i;
-
- /* loop through the fences to see what things can be processed */
-
- for (i = 0; i < DRM_KGSL_NUM_FENCE_ENTRIES; i++) {
- fence = &gem_buf_fence[i];
- if (!fence->ts_valid || fence->ts_device != code)
- continue;
-
- if (kgsl_check_timestamp(device, fence->timestamp))
- wakeup_fence_entries(fence);
- }
-
- return 0;
-}
-
int
kgsl_gem_lock_handle_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -1608,11 +1464,9 @@
};
static struct drm_driver driver = {
- .driver_features = DRIVER_USE_PLATFORM_DEVICE | DRIVER_GEM,
+ .driver_features = DRIVER_GEM,
.load = kgsl_drm_load,
.unload = kgsl_drm_unload,
- .firstopen = kgsl_drm_firstopen,
- .lastclose = kgsl_drm_lastclose,
.preclose = kgsl_drm_preclose,
.suspend = kgsl_drm_suspend,
.resume = kgsl_drm_resume,
@@ -1643,8 +1497,13 @@
{
int i;
+ /* Only initialize once */
+ if (kgsl_drm_inited == DRM_KGSL_INITED)
+ return 0;
+
+ kgsl_drm_inited = DRM_KGSL_INITED;
+
driver.num_ioctls = DRM_ARRAY_SIZE(kgsl_drm_ioctls);
- driver.platform_device = dev;
INIT_LIST_HEAD(&kgsl_mem_list);
@@ -1654,10 +1513,11 @@
gem_buf_fence[i].fence_id = ENTRY_EMPTY;
}
- return drm_init(&driver);
+ return drm_platform_init(&driver, dev);
}
void kgsl_drm_exit(void)
{
- drm_exit(&driver);
+ kgsl_drm_inited = DRM_KGSL_NOT_INITED;
+ drm_platform_exit(&driver, driver.kdriver.platform_device);
}
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 36248ef..671479e 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/iommu.h>
+#include <mach/socinfo.h>
#include "kgsl.h"
#include "kgsl_mmu.h"
@@ -534,9 +535,16 @@
int ret;
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
- memdesc->gpuaddr = memdesc->physaddr;
- return 0;
+ if (memdesc->sglen == 1) {
+ memdesc->gpuaddr = sg_phys(memdesc->sg);
+ return 0;
+ } else {
+ KGSL_CORE_ERR("Memory is not contigious "
+ "(sglen = %d)\n", memdesc->sglen);
+ return -EINVAL;
+ }
}
+
memdesc->gpuaddr = gen_pool_alloc_aligned(pagetable->pool,
memdesc->size, KGSL_MMU_ALIGN_SHIFT);
@@ -712,7 +720,14 @@
void kgsl_mmu_set_mmutype(char *mmutype)
{
- kgsl_mmu_type = iommu_found() ? KGSL_MMU_TYPE_IOMMU : KGSL_MMU_TYPE_GPU;
+ /* Set the default MMU - GPU on <=8960 and nothing on >= 8064 */
+ kgsl_mmu_type =
+ cpu_is_apq8064() ? KGSL_MMU_TYPE_NONE : KGSL_MMU_TYPE_GPU;
+
+ /* Use the IOMMU if it is found */
+ if (iommu_found())
+ kgsl_mmu_type = KGSL_MMU_TYPE_IOMMU;
+
if (mmutype && !strncmp(mmutype, "gpummu", 6))
kgsl_mmu_type = KGSL_MMU_TYPE_GPU;
if (iommu_found() && mmutype && !strncmp(mmutype, "iommu", 5))
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index f99a546..c8b4707 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -303,6 +303,22 @@
return 0;
}
+/*
+ * Before calling qup_config_core_on_en(), please make
+ * sure that QuPE core is in RESET state.
+ */
+static void
+qup_config_core_on_en(struct qup_i2c_dev *dev)
+{
+ uint32_t status;
+
+ status = readl_relaxed(dev->base + QUP_CONFIG);
+ status |= BIT(13);
+ writel_relaxed(status, dev->base + QUP_CONFIG);
+ /* making sure that write has really gone through */
+ mb();
+}
+
static void
qup_i2c_pwr_mgmt(struct qup_i2c_dev *dev, unsigned int state)
{
@@ -313,6 +329,7 @@
} else {
qup_update_state(dev, QUP_RESET_STATE);
clk_disable_unprepare(dev->clk);
+ qup_config_core_on_en(dev);
clk_disable_unprepare(dev->pclk);
}
}
diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c
index 025b756..46199d8 100644
--- a/drivers/leds/leds-pm8xxx.c
+++ b/drivers/leds/leds-pm8xxx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,46 @@
#define PM8XXX_DRV_LED_CTRL_MASK 0xf8
#define PM8XXX_DRV_LED_CTRL_SHIFT 0x03
+#define SSBI_REG_ADDR_WLED_CTRL_BASE 0x25A
+#define SSBI_REG_ADDR_WLED_CTRL(n) (SSBI_REG_ADDR_WLED_CTRL_BASE + (n) - 1)
+
+/* wled control registers */
+#define WLED_MOD_CTRL_REG SSBI_REG_ADDR_WLED_CTRL(1)
+#define WLED_MAX_CURR_CFG_REG(n) SSBI_REG_ADDR_WLED_CTRL(n + 2)
+#define WLED_BRIGHTNESS_CNTL_REG1(n) SSBI_REG_ADDR_WLED_CTRL(n + 5)
+#define WLED_BRIGHTNESS_CNTL_REG2(n) SSBI_REG_ADDR_WLED_CTRL(n + 6)
+#define WLED_SYNC_REG SSBI_REG_ADDR_WLED_CTRL(11)
+#define WLED_OVP_CFG_REG SSBI_REG_ADDR_WLED_CTRL(13)
+#define WLED_BOOST_CFG_REG SSBI_REG_ADDR_WLED_CTRL(14)
+#define WLED_HIGH_POLE_CAP_REG SSBI_REG_ADDR_WLED_CTRL(16)
+
+#define WLED_STRINGS 0x03
+#define WLED_OVP_VAL_MASK 0x30
+#define WLED_OVP_VAL_BIT_SHFT 0x04
+#define WLED_BOOST_LIMIT_MASK 0xE0
+#define WLED_BOOST_LIMIT_BIT_SHFT 0x05
+#define WLED_EN_MASK 0x01
+#define WLED_CP_SELECT_MAX 0x03
+#define WLED_CP_SELECT_MASK 0x03
+#define WLED_DIG_MOD_GEN_MASK 0x70
+#define WLED_CS_OUT_MASK 0x0E
+#define WLED_CTL_DLY_STEP 200
+#define WLED_CTL_DLY_MAX 1400
+#define WLED_CTL_DLY_MASK 0xE0
+#define WLED_CTL_DLY_BIT_SHFT 0x05
+#define WLED_MAX_CURR 25
+#define WLED_MAX_CURR_MASK 0x1F
+#define WLED_OP_FDBCK_MASK 0x1C
+#define WLED_OP_FDBCK_BIT_SHFT 0x02
+
+#define WLED_MAX_LEVEL 100
+#define WLED_8_BIT_MASK 0xFF
+#define WLED_8_BIT_SHFT 0x08
+#define WLED_MAX_DUTY_CYCLE 0xFFF
+
+#define WLED_SYNC_VAL 0x07
+#define WLED_SYNC_RESET_VAL 0x00
+
#define MAX_FLASH_LED_CURRENT 300
#define MAX_LC_LED_CURRENT 40
#define MAX_KP_BL_LED_CURRENT 300
@@ -81,6 +121,8 @@
int pwm_channel;
u32 pwm_period_us;
struct pm8xxx_pwm_duty_cycles *pwm_duty_cycles;
+ struct wled_config_data *wled_cfg;
+ int max_current;
};
static void led_kp_set(struct pm8xxx_led_data *led, enum led_brightness value)
@@ -145,6 +187,79 @@
led->id, rc);
}
+static int
+led_wled_set(struct pm8xxx_led_data *led, enum led_brightness value)
+{
+ int rc, duty;
+ u8 val, i, num_wled_strings;
+
+ if (value > WLED_MAX_LEVEL)
+ value = WLED_MAX_LEVEL;
+
+ duty = (WLED_MAX_DUTY_CYCLE * value) / WLED_MAX_LEVEL;
+
+ num_wled_strings = led->wled_cfg->num_strings;
+
+ /* program brightness control registers */
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = pm8xxx_readb(led->dev->parent,
+ WLED_BRIGHTNESS_CNTL_REG1(i), &val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't read wled brightnes ctrl"
+ " register1 rc=%d\n", rc);
+ return rc;
+ }
+
+ val = (val & ~WLED_MAX_CURR_MASK) | (duty >> WLED_8_BIT_SHFT);
+ rc = pm8xxx_writeb(led->dev->parent,
+ WLED_BRIGHTNESS_CNTL_REG1(i), val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't write wled brightness ctrl"
+ " register1 rc=%d\n", rc);
+ return rc;
+ }
+
+ val = duty & WLED_8_BIT_MASK;
+ rc = pm8xxx_writeb(led->dev->parent,
+ WLED_BRIGHTNESS_CNTL_REG2(i), val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't write wled brightness ctrl"
+ " register2 rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ /* sync */
+ val = WLED_SYNC_VAL;
+ rc = pm8xxx_writeb(led->dev->parent, WLED_SYNC_REG, val);
+ if (rc) {
+ dev_err(led->dev->parent,
+ "can't read wled sync register rc=%d\n", rc);
+ return rc;
+ }
+
+ val = WLED_SYNC_RESET_VAL;
+ rc = pm8xxx_writeb(led->dev->parent, WLED_SYNC_REG, val);
+ if (rc) {
+ dev_err(led->dev->parent,
+ "can't read wled sync register rc=%d\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
+static void wled_dump_regs(struct pm8xxx_led_data *led)
+{
+ int i;
+ u8 val;
+
+ for (i = 1; i < 17; i++) {
+ pm8xxx_readb(led->dev->parent,
+ SSBI_REG_ADDR_WLED_CTRL(i), &val);
+ pr_debug("WLED_CTRL_%d = 0x%x\n", i, val);
+ }
+}
+
static int pm8xxx_led_pwm_work(struct pm8xxx_led_data *led)
{
int duty_us;
@@ -168,21 +283,31 @@
static void __pm8xxx_led_work(struct pm8xxx_led_data *led,
enum led_brightness level)
{
+ int rc;
+
mutex_lock(&led->lock);
switch (led->id) {
case PM8XXX_ID_LED_KB_LIGHT:
led_kp_set(led, level);
- break;
+ break;
case PM8XXX_ID_LED_0:
case PM8XXX_ID_LED_1:
case PM8XXX_ID_LED_2:
led_lc_set(led, level);
- break;
+ break;
case PM8XXX_ID_FLASH_LED_0:
case PM8XXX_ID_FLASH_LED_1:
led_flash_set(led, level);
- break;
+ break;
+ case PM8XXX_ID_WLED:
+ rc = led_wled_set(led, level);
+ if (rc < 0)
+ pr_err("wled brightness set failed %d\n", rc);
+ break;
+ default:
+ dev_err(led->cdev.dev, "unknown led id %d", led->id);
+ break;
}
mutex_unlock(&led->lock);
@@ -261,6 +386,9 @@
break;
}
break;
+ case PM8XXX_ID_WLED:
+ led->cdev.max_brightness = WLED_MAX_LEVEL;
+ break;
default:
rc = -EINVAL;
pr_err("LED Id is invalid");
@@ -279,6 +407,149 @@
return led->cdev.brightness;
}
+static int __devinit init_wled(struct pm8xxx_led_data *led)
+{
+ int rc, i;
+ u8 val, num_wled_strings;
+
+ num_wled_strings = led->wled_cfg->num_strings;
+
+ /* program over voltage protection threshold */
+ if (led->wled_cfg->ovp_val > WLED_OVP_37V) {
+ dev_err(led->dev->parent, "Invalid ovp value");
+ return -EINVAL;
+ }
+
+ rc = pm8xxx_readb(led->dev->parent, WLED_OVP_CFG_REG, &val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't read wled ovp config"
+ " register rc=%d\n", rc);
+ return rc;
+ }
+
+ val = (val & ~WLED_OVP_VAL_MASK) |
+ (led->wled_cfg->ovp_val << WLED_OVP_VAL_BIT_SHFT);
+
+ rc = pm8xxx_writeb(led->dev->parent, WLED_OVP_CFG_REG, val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't write wled ovp config"
+ " register rc=%d\n", rc);
+ return rc;
+ }
+
+ /* program current boost limit and output feedback*/
+ if (led->wled_cfg->boost_curr_lim > WLED_CURR_LIMIT_1680mA) {
+ dev_err(led->dev->parent, "Invalid boost current limit");
+ return -EINVAL;
+ }
+
+ rc = pm8xxx_readb(led->dev->parent, WLED_BOOST_CFG_REG, &val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't read wled boost config"
+ " register rc=%d\n", rc);
+ return rc;
+ }
+
+ val = (val & ~WLED_BOOST_LIMIT_MASK) |
+ (led->wled_cfg->boost_curr_lim << WLED_BOOST_LIMIT_BIT_SHFT);
+
+ val = (val & ~WLED_OP_FDBCK_MASK) |
+ (led->wled_cfg->op_fdbck << WLED_OP_FDBCK_BIT_SHFT);
+
+ rc = pm8xxx_writeb(led->dev->parent, WLED_BOOST_CFG_REG, val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't write wled boost config"
+ " register rc=%d\n", rc);
+ return rc;
+ }
+
+ /* program high pole capacitance */
+ if (led->wled_cfg->cp_select > WLED_CP_SELECT_MAX) {
+ dev_err(led->dev->parent, "Invalid pole capacitance");
+ return -EINVAL;
+ }
+
+ rc = pm8xxx_readb(led->dev->parent, WLED_HIGH_POLE_CAP_REG, &val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't read wled high pole"
+ " capacitance register rc=%d\n", rc);
+ return rc;
+ }
+
+ val = (val & ~WLED_CP_SELECT_MASK) | led->wled_cfg->cp_select;
+
+ rc = pm8xxx_writeb(led->dev->parent, WLED_HIGH_POLE_CAP_REG, val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't write wled high pole"
+ " capacitance register rc=%d\n", rc);
+ return rc;
+ }
+
+ /* program activation delay and maximum current */
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = pm8xxx_readb(led->dev->parent,
+ WLED_MAX_CURR_CFG_REG(i + 2), &val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't read wled max current"
+ " config register rc=%d\n", rc);
+ return rc;
+ }
+
+ if ((led->wled_cfg->ctrl_delay_us % WLED_CTL_DLY_STEP) ||
+ (led->wled_cfg->ctrl_delay_us > WLED_CTL_DLY_MAX)) {
+ dev_err(led->dev->parent, "Invalid control delay\n");
+ return rc;
+ }
+
+ val = val / WLED_CTL_DLY_STEP;
+ val = (val & ~WLED_CTL_DLY_MASK) |
+ (led->wled_cfg->ctrl_delay_us << WLED_CTL_DLY_BIT_SHFT);
+
+ if ((led->max_current > WLED_MAX_CURR)) {
+ dev_err(led->dev->parent, "Invalid max current\n");
+ return -EINVAL;
+ }
+
+ val = (val & ~WLED_MAX_CURR_MASK) | led->max_current;
+
+ rc = pm8xxx_writeb(led->dev->parent,
+ WLED_MAX_CURR_CFG_REG(i + 2), val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't write wled max current"
+ " config register rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ /* program digital module generator, cs out and enable the module */
+ rc = pm8xxx_readb(led->dev->parent, WLED_MOD_CTRL_REG, &val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't read wled module ctrl"
+ " register rc=%d\n", rc);
+ return rc;
+ }
+
+ if (led->wled_cfg->dig_mod_gen_en)
+ val |= WLED_DIG_MOD_GEN_MASK;
+
+ if (led->wled_cfg->cs_out_en)
+ val |= WLED_CS_OUT_MASK;
+
+ val |= WLED_EN_MASK;
+
+ rc = pm8xxx_writeb(led->dev->parent, WLED_MOD_CTRL_REG, val);
+ if (rc) {
+ dev_err(led->dev->parent, "can't write wled module ctrl"
+ " register rc=%d\n", rc);
+ return rc;
+ }
+
+ /* dump wled registers */
+ wled_dump_regs(led);
+
+ return 0;
+}
+
static int __devinit get_init_value(struct pm8xxx_led_data *led, u8 *val)
{
int rc, offset;
@@ -300,6 +571,15 @@
case PM8XXX_ID_FLASH_LED_1:
addr = SSBI_REG_ADDR_FLASH_DRV1;
break;
+ case PM8XXX_ID_WLED:
+ rc = init_wled(led);
+ if (rc)
+ dev_err(led->cdev.dev, "can't initialize wled rc=%d\n",
+ rc);
+ return rc;
+ default:
+ dev_err(led->cdev.dev, "unknown led id %d", led->id);
+ return -EINVAL;
}
rc = pm8xxx_readb(led->dev->parent, addr, val);
@@ -351,6 +631,7 @@
return rc;
}
+
static int __devinit pm8xxx_led_probe(struct platform_device *pdev)
{
const struct pm8xxx_led_platform_data *pdata = pdev->dev.platform_data;
@@ -388,9 +669,11 @@
led_dat->pwm_channel = led_cfg->pwm_channel;
led_dat->pwm_period_us = led_cfg->pwm_period_us;
led_dat->pwm_duty_cycles = led_cfg->pwm_duty_cycles;
+ led_dat->wled_cfg = led_cfg->wled_cfg;
+ led_dat->max_current = led_cfg->max_current;
if (!((led_dat->id >= PM8XXX_ID_LED_KB_LIGHT) &&
- (led_dat->id <= PM8XXX_ID_FLASH_LED_1))) {
+ (led_dat->id < PM8XXX_ID_MAX))) {
dev_err(&pdev->dev, "invalid LED ID (%d) specified\n",
led_dat->id);
rc = -EINVAL;
@@ -424,6 +707,12 @@
goto fail_id_check;
}
+ /* configure default state */
+ if (led_cfg->default_state)
+ led->cdev.brightness = led_dat->cdev.max_brightness;
+ else
+ led->cdev.brightness = LED_OFF;
+
if (led_cfg->mode != PM8XXX_LED_MODE_MANUAL) {
__pm8xxx_led_work(led_dat,
led_dat->cdev.max_brightness);
@@ -436,9 +725,10 @@
"configure LED, error: %d\n", rc);
goto fail_id_check;
}
+ schedule_work(&led->work);
}
} else {
- __pm8xxx_led_work(led_dat, LED_OFF);
+ __pm8xxx_led_work(led_dat, led->cdev.brightness);
}
}
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index b1dc87e..ca44c34 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -226,3 +226,11 @@
by QUP in the board file as QUP is used by
applications other than camera.
+config S5K3L1YX
+ bool "Sensor S5K3L1YX (BAYER 12M)"
+ depends on MSM_CAMERA
+ ---help---
+ Samsung 12 MP Bayer Sensor with auto focus, uses
+ 4 mipi lanes, preview config = 1984 * 1508 at 30 fps,
+ snapshot config = 4000 * 3000 at 20 fps,
+ hfr video at 60, 90 and 120 fps.
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index af61bd2..86d62c9 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -73,43 +73,54 @@
static struct ispif_device *ispif;
+atomic_t ispif_irq_cnt;
+spinlock_t ispif_tasklet_lock;
+struct list_head ispif_tasklet_q;
static uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
-static int msm_ispif_intf_reset(uint8_t intftype)
+
+static int msm_ispif_intf_reset(uint8_t intfmask)
{
int rc = 0;
- uint32_t data;
+ uint32_t data = 0x1;
+ uint8_t intfnum = 0, mask = intfmask;
+ while (mask != 0) {
+ if (!(intfmask & (0x1 << intfnum))) {
+ mask >>= 1;
+ intfnum++;
+ continue;
+ }
+ switch (intfnum) {
+ case PIX0:
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << PIX_VFE_RST_STB) +
+ (0x1 << PIX_CSID_RST_STB);
+ break;
- switch (intftype) {
- case PIX0:
- data = (0x1 << STROBED_RST_EN) +
- (0x1 << PIX_VFE_RST_STB) +
- (0x1 << PIX_CSID_RST_STB);
+ case RDI0:
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << RDI_VFE_RST_STB) +
+ (0x1 << RDI_CSID_RST_STB);
+ break;
+
+ case RDI1:
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << RDI_1_VFE_RST_STB) +
+ (0x1 << RDI_1_CSID_RST_STB);
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ mask >>= 1;
+ intfnum++;
+ } /*end while */
+ if (rc >= 0) {
msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- break;
-
- case RDI0:
- data = (0x1 << STROBED_RST_EN) +
- (0x1 << RDI_VFE_RST_STB) +
- (0x1 << RDI_CSID_RST_STB);
- msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- break;
-
- case RDI1:
- data = (0x1 << STROBED_RST_EN) +
- (0x1 << RDI_1_VFE_RST_STB) +
- (0x1 << RDI_1_CSID_RST_STB);
- msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- break;
-
- default:
- rc = -EINVAL;
- break;
+ rc = wait_for_completion_interruptible(&ispif->reset_complete);
}
- if (rc >= 0)
- rc = wait_for_completion_interruptible(
- &ispif->reset_complete);
return rc;
}
@@ -244,97 +255,109 @@
}
static void
-msm_ispif_intf_cmd(uint8_t intftype, uint8_t intf_cmd_mask)
+msm_ispif_intf_cmd(uint8_t intfmask, uint8_t intf_cmd_mask)
{
uint8_t vc = 0, val = 0;
- uint32_t cid_mask = msm_ispif_get_cid_mask(intftype);
-
- while (cid_mask != 0) {
- if ((cid_mask & 0xf) != 0x0) {
- val = (intf_cmd_mask>>(vc*2)) & 0x3;
- global_intf_cmd_mask &= ~((0x3 & ~val)
- <<((vc*2)+(intftype*8)));
- CDBG("intf cmd 0x%x\n", global_intf_cmd_mask);
- msm_io_w(global_intf_cmd_mask,
- ispif->base + ISPIF_INTF_CMD_ADDR);
+ uint8_t mask = intfmask, intfnum = 0;
+ uint32_t cid_mask = 0;
+ while (mask != 0) {
+ if (!(intfmask & (0x1 << intfnum))) {
+ mask >>= 1;
+ intfnum++;
+ continue;
}
- vc++;
- cid_mask >>= 4;
+
+ cid_mask = msm_ispif_get_cid_mask(intfnum);
+ vc = 0;
+
+ while (cid_mask != 0) {
+ if ((cid_mask & 0xf) != 0x0) {
+ val = (intf_cmd_mask>>(vc*2)) & 0x3;
+ global_intf_cmd_mask |=
+ (0x3 << ((vc * 2) + (intfnum * 8)));
+ global_intf_cmd_mask &= ~((0x3 & ~val)
+ << ((vc * 2) +
+ (intfnum * 8)));
+ }
+ vc++;
+ cid_mask >>= 4;
+ }
+ mask >>= 1;
+ intfnum++;
}
+ msm_io_w(global_intf_cmd_mask, ispif->base + ISPIF_INTF_CMD_ADDR);
}
-static int msm_ispif_abort_intf_transfer(uint8_t intf)
+static int msm_ispif_abort_intf_transfer(uint8_t intfmask)
{
int rc = 0;
uint8_t intf_cmd_mask = 0xAA;
-
- CDBG("abort stream request\n");
+ uint8_t intfnum = 0, mask = intfmask;
mutex_lock(&ispif->mutex);
- msm_ispif_intf_cmd(intf, intf_cmd_mask);
- rc = msm_ispif_intf_reset(intf);
- global_intf_cmd_mask |= 0xFF<<(intf * 8);
+ msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
+ while (mask != 0) {
+ if (intfmask & (0x1 << intfnum))
+ global_intf_cmd_mask |= (0xFF << (intfnum * 8));
+ mask >>= 1;
+ intfnum++;
+ }
mutex_unlock(&ispif->mutex);
return rc;
}
-static int msm_ispif_start_intf_transfer(uint8_t intf)
+static int msm_ispif_start_intf_transfer(uint8_t intfmask)
{
- uint32_t data;
uint8_t intf_cmd_mask = 0x55;
int rc = 0;
-
- CDBG("start stream request\n");
mutex_lock(&ispif->mutex);
- switch (intf) {
- case PIX0:
- data = msm_io_r(ispif->base + ISPIF_PIX_STATUS_ADDR);
- if ((data & 0xf) != 0xf) {
- CDBG("interface is busy\n");
- mutex_unlock(&ispif->mutex);
- return -EBUSY;
- }
- break;
-
- case RDI0:
- data = msm_io_r(ispif->base + ISPIF_RDI_STATUS_ADDR);
- ispif->start_ack_pending = 1;
- break;
-
- case RDI1:
- data = msm_io_r(ispif->base + ISPIF_RDI_1_STATUS_ADDR);
- ispif->start_ack_pending = 1;
- break;
- }
- msm_ispif_intf_cmd(intf, intf_cmd_mask);
+ rc = msm_ispif_intf_reset(intfmask);
+ msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
mutex_unlock(&ispif->mutex);
return rc;
}
-static int msm_ispif_stop_intf_transfer(uint8_t intf)
+static int msm_ispif_stop_intf_transfer(uint8_t intfmask)
{
int rc = 0;
uint8_t intf_cmd_mask = 0x00;
- CDBG("stop stream request\n");
+ uint8_t intfnum = 0, mask = intfmask;
mutex_lock(&ispif->mutex);
- msm_ispif_intf_cmd(intf, intf_cmd_mask);
- switch (intf) {
- case PIX0:
- while ((msm_io_r(ispif->base + ISPIF_PIX_STATUS_ADDR)
- & 0xf) != 0xf) {
- CDBG("Wait for Idle\n");
- }
- break;
+ msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
+ while (mask != 0) {
+ if (intfmask & (0x1 << intfnum)) {
+ switch (intfnum) {
+ case PIX0:
+ while ((msm_io_r(ispif->base +
+ ISPIF_PIX_STATUS_ADDR)
+ & 0xf) != 0xf) {
+ CDBG("Wait for pix0 Idle\n");
+ }
+ break;
- case RDI0:
- while ((msm_io_r(ispif->base + ISPIF_RDI_STATUS_ADDR)
- & 0xf) != 0xf) {
- CDBG("Wait for Idle\n");
+ case RDI0:
+ while ((msm_io_r(ispif->base +
+ ISPIF_RDI_STATUS_ADDR)
+ & 0xf) != 0xf) {
+ CDBG("Wait for rdi0 Idle\n");
+ }
+ break;
+
+ case RDI1:
+ while ((msm_io_r(ispif->base +
+ ISPIF_RDI_1_STATUS_ADDR)
+ & 0xf) != 0xf) {
+ CDBG("Wait for rdi1 Idle\n");
+ }
+ break;
+
+ default:
+ break;
+ }
+ global_intf_cmd_mask |= (0xFF << (intfnum * 8));
}
- break;
- default:
- break;
+ mask >>= 1;
+ intfnum++;
}
- global_intf_cmd_mask |= 0xFF<<(intf * 8);
mutex_unlock(&ispif->mutex);
return rc;
}
@@ -364,10 +387,77 @@
return rc;
}
+static void ispif_do_tasklet(unsigned long data)
+{
+ unsigned long flags;
+
+ struct ispif_isr_queue_cmd *qcmd = NULL;
+ CDBG("=== ispif_do_tasklet start ===\n");
+
+ while (atomic_read(&ispif_irq_cnt)) {
+ spin_lock_irqsave(&ispif_tasklet_lock, flags);
+ qcmd = list_first_entry(&ispif_tasklet_q,
+ struct ispif_isr_queue_cmd, list);
+ atomic_sub(1, &ispif_irq_cnt);
+
+ if (!qcmd) {
+ spin_unlock_irqrestore(&ispif_tasklet_lock,
+ flags);
+ return;
+ }
+ list_del(&qcmd->list);
+ spin_unlock_irqrestore(&ispif_tasklet_lock,
+ flags);
+ if (qcmd->ispifInterruptStatus0 &
+ ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
+ CDBG("ispif rdi irq status\n");
+ }
+ if (qcmd->ispifInterruptStatus1 &
+ ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
+ CDBG("ispif rdi1 irq status\n");
+ }
+ kfree(qcmd);
+ }
+ CDBG("=== ispif_do_tasklet end ===\n");
+}
+
+DECLARE_TASKLET(ispif_tasklet, ispif_do_tasklet, 0);
+
+static void ispif_process_irq(struct ispif_irq_status *out)
+{
+ unsigned long flags;
+ struct ispif_isr_queue_cmd *qcmd;
+
+ CDBG("ispif_process_irq\n");
+ qcmd = kzalloc(sizeof(struct ispif_isr_queue_cmd),
+ GFP_ATOMIC);
+ if (!qcmd) {
+ pr_err("ispif_process_irq: qcmd malloc failed!\n");
+ return;
+ }
+ qcmd->ispifInterruptStatus0 = out->ispifIrqStatus0;
+ qcmd->ispifInterruptStatus1 = out->ispifIrqStatus1;
+
+ spin_lock_irqsave(&ispif_tasklet_lock, flags);
+ list_add_tail(&qcmd->list, &ispif_tasklet_q);
+
+ atomic_add(1, &ispif_irq_cnt);
+ spin_unlock_irqrestore(&ispif_tasklet_lock, flags);
+ tasklet_schedule(&ispif_tasklet);
+ return;
+}
+
static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out)
{
out->ispifIrqStatus0 = msm_io_r(ispif->base +
- ISPIF_IRQ_STATUS_ADDR);
+ ISPIF_IRQ_STATUS_ADDR);
+ out->ispifIrqStatus1 = msm_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_1_ADDR);
+ msm_io_w(out->ispifIrqStatus0,
+ ispif->base + ISPIF_IRQ_CLEAR_ADDR);
+ msm_io_w(out->ispifIrqStatus1,
+ ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+
CDBG("ispif->irq: Irq_status0 = 0x%x\n",
out->ispifIrqStatus0);
if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
@@ -377,23 +467,14 @@
pr_err("%s: pix intf 0 overflow.\n", __func__);
if (out->ispifIrqStatus0 & (0x1 << RAW_INTF_0_OVERFLOW_IRQ))
pr_err("%s: rdi intf 0 overflow.\n", __func__);
- if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
- if (ispif->start_ack_pending) {
- v4l2_subdev_notify(&ispif->subdev,
- NOTIFY_ISP_MSG_EVT,
- (void *)MSG_ID_START_ACK);
- ispif->start_ack_pending = 0;
- /* stop stream at frame boundary */
- msm_ispif_stop_intf_transfer(RDI0);
- }
- v4l2_subdev_notify(&ispif->subdev, NOTIFY_ISP_MSG_EVT,
- (void *)MSG_ID_SOF_ACK);
+ if ((out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_RDI_SOF_MASK) ||
+ (out->ispifIrqStatus1 &
+ ISPIF_IRQ_STATUS_RDI_SOF_MASK)) {
+ ispif_process_irq(out);
}
}
- msm_io_w(out->ispifIrqStatus0,
- ispif->base + ISPIF_IRQ_CLEAR_ADDR);
msm_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
- ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
}
static irqreturn_t msm_io_ispif_irq(int irq_num, void *data)
@@ -414,6 +495,8 @@
static int msm_ispif_init(const uint32_t *csid_version)
{
int rc = 0;
+ spin_lock_init(&ispif_tasklet_lock);
+ INIT_LIST_HEAD(&ispif_tasklet_q);
rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
IRQF_TRIGGER_RISING, "ispif", 0);
@@ -451,6 +534,7 @@
CDBG("%s, free_irq\n", __func__);
free_irq(ispif->irq->start, 0);
+ tasklet_kill(&ispif_tasklet);
}
void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num)
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index deadc28..8f1dd12 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -36,6 +36,12 @@
struct clk *ispif_clk[5];
};
+struct ispif_isr_queue_cmd {
+ struct list_head list;
+ uint32_t ispifInterruptStatus0;
+ uint32_t ispifInterruptStatus1;
+};
+
#define VIDIOC_MSM_ISPIF_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_ispif_params)
@@ -51,6 +57,12 @@
#define ISPIF_OFF_IMMEDIATELY (0x01 << 2)
#define ISPIF_S_STREAM_SHIFT 4
+
+#define PIX_0 (0x01 << 0)
+#define RDI_0 (0x01 << 1)
+#define PIX_1 (0x01 << 2)
+#define RDI_1 (0x01 << 3)
+
void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num);
#endif
diff --git a/drivers/media/video/msm/io/msm_io_util.c b/drivers/media/video/msm/io/msm_io_util.c
index 0ae247e..207f8be 100644
--- a/drivers/media/video/msm/io/msm_io_util.c
+++ b/drivers/media/video/msm/io/msm_io_util.c
@@ -40,29 +40,42 @@
goto cam_clk_set_err;
}
}
+ rc = clk_prepare(clk_ptr[i]);
+ if (rc < 0) {
+ pr_err("%s prepare failed\n",
+ clk_info[i].clk_name);
+ goto cam_clk_prepare_err;
+ }
+
rc = clk_enable(clk_ptr[i]);
if (rc < 0) {
pr_err("%s enable failed\n",
clk_info[i].clk_name);
- goto cam_clk_set_err;
+ goto cam_clk_enable_err;
}
}
} else {
for (i = num_clk - 1; i >= 0; i--) {
- if (clk_ptr[i] != NULL)
+ if (clk_ptr[i] != NULL) {
clk_disable(clk_ptr[i]);
+ clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]);
+ }
}
}
return rc;
+cam_clk_enable_err:
+ clk_unprepare(clk_ptr[i]);
+cam_clk_prepare_err:
cam_clk_set_err:
clk_put(clk_ptr[i]);
cam_clk_get_err:
for (i--; i >= 0; i--) {
if (clk_ptr[i] != NULL) {
clk_disable(clk_ptr[i]);
+ clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]);
}
}
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 22322b8..7680559 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -116,6 +116,7 @@
NOTIFY_ISP_MSG_EVT, /* arg = enum ISP_MESSAGE_ID */
NOTIFY_VFE_MSG_OUT, /* arg = struct isp_msg_output */
NOTIFY_VFE_MSG_STATS, /* arg = struct isp_msg_stats */
+ NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
NOTIFY_VPE_MSG_EVT,
@@ -426,7 +427,7 @@
int msg_type, struct msm_free_buf *buf,
uint32_t frame_id);
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
- int msg_type, struct msm_free_buf *frame, int dirty);
+ int msg_type, struct msm_free_buf *frame, int dirty, int node_type);
int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
int path, struct msm_free_buf *free_buf);
@@ -473,7 +474,7 @@
int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
struct msm_mctl_pp_frame_info *pp_frame_info);
int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
- int out_type);
+ int out_type, int node_type);
struct msm_frame_buffer *msm_mctl_buf_find(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 79294a3..d111452 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -29,6 +29,7 @@
static struct clk *camio_jpeg_clk;
static struct clk *camio_jpeg_pclk;
+static struct clk *camio_imem_clk;
static struct regulator *fs_ijpeg;
static struct platform_device *camio_dev;
@@ -129,6 +130,11 @@
clk = clk_get(NULL, "ijpeg_pclk");
break;
+ case CAMIO_IMEM_CLK:
+ camio_imem_clk =
+ clk = clk_get(NULL, "imem_clk");
+ break;
+
default:
break;
}
@@ -158,6 +164,10 @@
clk = camio_jpeg_pclk;
break;
+ case CAMIO_IMEM_CLK:
+ clk = camio_imem_clk;
+ break;
+
default:
break;
}
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 6b3aef7..bb50d77 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -142,7 +142,7 @@
{
int rc = -EINVAL, image_mode;
struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
- struct msm_free_buf free_buf;
+ struct msm_free_buf free_buf, temp_free_buf;
struct msm_camvfe_params vfe_params;
struct msm_vfe_cfg_cmd cfgcmd;
struct msm_sync *sync =
@@ -190,7 +190,12 @@
vfe_params.vfe_cfg = &cfgcmd;
vfe_params.data = (void *)&free_buf;
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
- /* Write the same buffer into PONG */
+ temp_free_buf = free_buf;
+ if (msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ image_mode, &free_buf)) {
+ /* Write the same buffer into PONG */
+ free_buf = temp_free_buf;
+ }
cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
@@ -307,6 +312,36 @@
}
}
break;
+ case NOTIFY_VFE_MSG_COMP_STATS: {
+ struct msm_stats_buf *stats = (struct msm_stats_buf *)arg;
+ struct msm_stats_buf *stats_buf = NULL;
+
+ isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE;
+ stats->aec.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->aec.buff, &(stats->aec.fd));
+ stats->awb.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->awb.buff, &(stats->awb.fd));
+ stats->af.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->af.buff, &(stats->af.fd));
+ stats->ihist.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->ihist.buff, &(stats->ihist.fd));
+ stats->rs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->rs.buff, &(stats->rs.fd));
+ stats->cs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->cs.buff, &(stats->cs.fd));
+
+ stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC);
+ if (!stats_buf) {
+ pr_err("%s: out of memory.\n", __func__);
+ rc = -ENOMEM;
+ } else {
+ *stats_buf = *stats;
+ isp_event->isp_data.isp_msg.len =
+ sizeof(struct msm_stats_buf);
+ isp_event->isp_data.isp_msg.data = stats_buf;
+ }
+ }
+ break;
case NOTIFY_VFE_MSG_STATS: {
struct msm_stats_buf stats;
struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 2c4fbe4..13d1daf 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -241,6 +241,7 @@
case NOTIFY_ISP_MSG_EVT:
case NOTIFY_VFE_MSG_OUT:
case NOTIFY_VFE_MSG_STATS:
+ case NOTIFY_VFE_MSG_COMP_STATS:
case NOTIFY_VFE_BUF_EVT:
case NOTIFY_VFE_BUF_FREE_EVT:
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 1ab76fe..8148f1f 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -325,9 +325,13 @@
}
int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
- int image_mode)
+ int image_mode, int node_type)
{
- if ((image_mode >= 0) &&
+ if ((image_mode >= 0) && node_type &&
+ pmctl->sync.pcam_sync->mctl_node.dev_inst_map[image_mode])
+ return pmctl->sync.pcam_sync->
+ mctl_node.dev_inst_map[image_mode]->my_index;
+ else if ((image_mode >= 0) &&
pmctl->sync.pcam_sync->dev_inst_map[image_mode])
return pmctl->sync.pcam_sync->
dev_inst_map[image_mode]->my_index;
@@ -424,13 +428,13 @@
msm_mctl_check_pp(p_mctl, image_mode, &pp_divert_type, &pp_type);
D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x",
- __func__, pp_type, pp_divert_type, frame_id);
+ __func__, pp_type, pp_divert_type, frame_id);
if (pp_type || pp_divert_type)
rc = msm_mctl_do_pp_divert(p_mctl,
image_mode, fbuf, frame_id, pp_type);
else {
idx = msm_mctl_img_mode_to_inst_index(
- p_mctl, image_mode);
+ p_mctl, image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, dropping buffer\n",
__func__);
@@ -450,6 +454,22 @@
return 0;
}
+static int is_buffer_queued(struct msm_cam_v4l2_device *pcam, int image_mode)
+{
+ int idx;
+ int ret = 0;
+ struct msm_frame_buffer *buf = NULL;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+ if (buf->state != MSM_BUFFER_STATE_QUEUED)
+ continue;
+ ret = 1;
+ }
+ return ret;
+}
+
struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
struct msm_cam_media_controller *pmctl,
int image_mode)
@@ -462,22 +482,39 @@
/* Valid image mode. Search the mctl node first.
* If mctl node doesnt have the instance, then
* search in the user's video node */
- if (pcam->mctl_node.dev_inst_map[image_mode]) {
- idx =
- pcam->mctl_node.dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->mctl_node.dev_inst[idx];
- D("%s Found instance %p in mctl node device\n",
+ if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
+ || pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (pcam->mctl_node.dev_inst_map[image_mode]
+ && is_buffer_queued(pcam, image_mode)) {
+ idx =
+ pcam->mctl_node.dev_inst_map[image_mode]
+ ->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device",
__func__, pcam_inst);
- } else if (pcam->dev_inst_map[image_mode]) {
- idx = pcam->dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->dev_inst[idx];
- D("%s Found instance %p in video device",
+ }
+ } else {
+ if (pcam->mctl_node.dev_inst_map[image_mode]) {
+ idx = pcam->mctl_node.dev_inst_map[image_mode]
+ ->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
__func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device",
+ __func__, pcam_inst);
+ }
}
} else
pr_err("%s Invalid image mode %d. Return NULL\n",
__func__, image_mode);
-
return pcam_inst;
}
@@ -597,19 +634,21 @@
return rc;
}
-int msm_mctl_buf_done_pp(
- struct msm_cam_media_controller *pmctl,
- int image_mode, struct msm_free_buf *frame, int dirty)
+int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
+ int image_mode, struct msm_free_buf *frame, int dirty, int node_type)
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
int rc = 0, idx;
- idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode);
+ idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode, node_type);
if (idx < 0) {
pr_err("%s Invalid instance, buffer not released\n", __func__);
return idx;
}
- pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ if (node_type)
+ pcam_inst = pmctl->sync.pcam_sync->mctl_node.dev_inst[idx];
+ else
+ pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
if (!pcam_inst) {
pr_err("%s Invalid instance, cannot send buf to user",
__func__);
@@ -638,7 +677,7 @@
int rc = -EINVAL, idx;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant get buffer\n", __func__);
return NULL;
@@ -677,7 +716,7 @@
struct msm_frame_buffer *buf = NULL;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant put buffer\n", __func__);
return idx;
@@ -712,7 +751,7 @@
int idx;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant delete buffer\n", __func__);
return idx;
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 1593e7e..82c5bf7 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -95,20 +95,95 @@
*pp_type = OUTPUT_TYPE_V;
break;
case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
+ pp_key = PP_THUMB;
+ if (p_mctl->pp_info.pp_key & pp_key)
+ *pp_divert_type = OUTPUT_TYPE_T;
if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
*pp_type = OUTPUT_TYPE_T;
break;
default:
break;
}
- if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
- *pp_divert_type = 0;
+ if (p_mctl->vfe_output_mode != VFE_OUTPUTS_MAIN_AND_THUMB &&
+ p_mctl->vfe_output_mode != VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
+ *pp_divert_type = 0;
+ }
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
D("%s: pp_type=%d, pp_divert_type = %d",
__func__, *pp_type, *pp_divert_type);
return rc;
}
+static int is_buf_in_queue(struct msm_cam_v4l2_device *pcam,
+ struct msm_free_buf *fbuf, int image_mode)
+{
+ struct msm_frame_buffer *buf = NULL, *tmp;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ unsigned long flags = 0;
+ struct videobuf2_contig_pmem *mem;
+ uint32_t buf_idx, offset = 0;
+ uint32_t buf_phyaddr = 0;
+ int idx;
+ idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+ list_for_each_entry_safe(buf, tmp,
+ &pcam_inst->free_vq, list) {
+ buf_idx = buf->vidbuf.v4l2_buf.index;
+ mem = vb2_plane_cookie(&buf->vidbuf, 0);
+ if (mem->buffer_type == VIDEOBUF2_MULTIPLE_PLANES)
+ offset = mem->offset.data_offset +
+ pcam_inst->buf_offset[buf_idx][0].data_offset;
+ else
+ offset = mem->offset.sp_off.y_off;
+ buf_phyaddr = (unsigned long)
+ videobuf2_to_pmem_contig(&buf->vidbuf, 0) +
+ offset;
+ D("%s vb_idx=%d,vb_paddr=0x%x ch0=0x%x\n",
+ __func__, buf->vidbuf.v4l2_buf.index,
+ buf_phyaddr, fbuf->ch_paddr[0]);
+ if (fbuf->ch_paddr[0] == buf_phyaddr) {
+ spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+ return 1;
+ }
+ }
+ spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+ return 0;
+}
+static struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst_for_divert(
+ struct msm_cam_media_controller *pmctl,
+ int image_mode, struct msm_free_buf *fbuf, int *node_type)
+{
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+ int idx;
+
+ if (image_mode >= 0) {
+ /* Valid image mode. Search the mctl node first.
+ * If mctl node doesnt have the instance, then
+ * search in the user's video node */
+ if (pcam->mctl_node.dev_inst_map[image_mode]
+ && is_buf_in_queue(pcam, fbuf, image_mode)) {
+ idx =
+ pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ *node_type = MCTL_NODE;
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ *node_type = VIDEO_NODE;
+ D("%s Found instance %p in video device",
+ __func__, pcam_inst);
+ } else
+ pr_err("%s Invalid image mode %d. Return NULL\n",
+ __func__, image_mode);
+ }
+ return pcam_inst;
+}
+
int msm_mctl_do_pp_divert(
struct msm_cam_media_controller *p_mctl,
int image_mode, struct msm_free_buf *fbuf,
@@ -120,8 +195,10 @@
struct msm_cam_evt_divert_frame div;
struct msm_frame_buffer *vb = NULL;
struct videobuf2_contig_pmem *mem;
+ int node;
- pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+ pcam_inst = msm_mctl_get_pcam_inst_for_divert
+ (p_mctl, image_mode, fbuf, &node);
if (!pcam_inst) {
pr_err("%s Invalid instance. Cannot divert frame.\n",
__func__);
@@ -155,6 +232,7 @@
* this buffer.*/
mem = vb2_plane_cookie(&vb->vidbuf, 0);
div.frame.path = mem->path;
+ div.frame.node_type = node;
if (mem->buffer_type == VIDEOBUF2_SINGLE_PLANE) {
/* This buffer contains only 1 plane. Use the
* single planar structure to store the info.*/
@@ -670,7 +748,7 @@
done_frame.vb =
pp_frame_info->dest_frame.handle;
msm_mctl_buf_done_pp(
- p_mctl, img_mode, &done_frame, 0);
+ p_mctl, img_mode, &done_frame, 0, 0);
D("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
__func__, done_frame.vb,
pp_frame_cmd->path, done_frame.ch_paddr[0]);
@@ -848,7 +926,7 @@
}
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
/* here buf.addr is phy_addr */
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+ rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty, 0);
return rc;
}
@@ -882,6 +960,9 @@
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
break;
case OUTPUT_TYPE_T:
+ msg_type = VFE_MSG_OUTPUT_T;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+ break;
default:
rc = -EFAULT;
goto err;
@@ -895,7 +976,8 @@
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
D("%s Frame done id: %d\n", __func__, frame.frame_id);
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+ rc = msm_mctl_buf_done_pp(p_mctl, image_mode,
+ &buf, dirty, frame.node_type);
return rc;
err:
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 4b86bd8..99d9911 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -547,6 +547,10 @@
memset(&(vfe32_ctrl->csStatsControl), 0,
sizeof(struct vfe_stats_control));
+
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+ vfe32_ctrl->snapshot_frame_cnt = 0;
}
static void vfe32_reset(void)
@@ -589,6 +593,7 @@
vfe32_ctrl->operation_mode = *p;
vfe32_ctrl->stats_comp = *(++p);
+ vfe32_ctrl->hfr_mode = *(++p);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
@@ -684,10 +689,16 @@
static void vfe32_start_common(void)
{
+ uint32_t irq_mask = 0x00E00021;
vfe32_ctrl->start_ack_pending = TRUE;
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
- msm_io_w(0x00EFE021, vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+ if (vfe32_ctrl->stats_comp)
+ irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
+ else
+ irq_mask |= 0x000FE000;
+
+ msm_io_w(irq_mask, vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
@@ -2363,6 +2374,23 @@
goto proc_general_done;
}
break;
+ case VFE_CMD_FRAME_SKIP_CFG:
+ if (cmd->length != vfe32_cmd[cmd->id].length)
+ return -EINVAL;
+
+ cmdp = kmalloc(vfe32_cmd[cmd->id].length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+
+ CHECKED_COPY_FROM_USER(cmdp);
+ msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ cmdp, (vfe32_cmd[cmd->id].length));
+ vfe32_ctrl->frame_skip_cnt = ((uint32_t)
+ *cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
+ vfe32_ctrl->frame_skip_pattern = (uint32_t)(*(cmdp + 2));
+ break;
default:
if (cmd->length != vfe32_cmd[cmd->id].length)
return -EINVAL;
@@ -2389,47 +2417,73 @@
static void vfe32_stats_af_ack(struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spin_lock_irqsave(&vfe32_ctrl->af_ack_lock, flags);
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->af_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->afStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->afStatsControl.ackPending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_awb_ack(struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spin_lock_irqsave(&vfe32_ctrl->awb_ack_lock, flags);
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->awb_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->awbStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->awbStatsControl.ackPending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_aec_ack(struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spin_lock_irqsave(&vfe32_ctrl->aec_ack_lock, flags);
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->aec_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->aecStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->aecStatsControl.ackPending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_ihist_ack(struct vfe_cmd_stats_ack *pAck)
{
+ unsigned long flags;
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->ihist_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->ihistStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_rs_ack(struct vfe_cmd_stats_ack *pAck)
{
+ unsigned long flags;
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->rs_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->rsStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->rsStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_cs_ack(struct vfe_cmd_stats_ack *pAck)
{
+ unsigned long flags;
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->cs_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->csStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->csStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
}
-
static inline void vfe32_read_irq_status(struct vfe32_irq_status *out)
{
uint32_t *temp;
@@ -2559,30 +2613,43 @@
(vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB)) {
/* in snapshot mode */
/* later we need to add check for live snapshot mode. */
- vfe32_ctrl->vfe_capture_count--;
- /* if last frame to be captured: */
- if (vfe32_ctrl->vfe_capture_count == 0) {
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- }
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- }
- msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
+ (vfe32_ctrl->snapshot_frame_cnt %
+ vfe32_ctrl->frame_skip_cnt))) {
+ vfe32_ctrl->vfe_capture_count--;
+ /* if last frame to be captured: */
+ if (vfe32_ctrl->vfe_capture_count == 0) {
+ /* stop the bus output:write master enable = 0*/
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out0.ch0]);
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out0.ch1]);
+ }
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out1.ch0]);
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out1.ch1]);
+ }
+ msm_io_w_mb
+ (CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
- /* then do reg_update. */
- msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- }
- } /* in snapshot mode. */
+ vfe32_ctrl->snapshot_frame_cnt = -1;
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+ } /*if snapshot count is 0*/
+ } /*if frame is not being dropped*/
+ vfe32_ctrl->snapshot_frame_cnt++;
+ /* then do reg_update. */
+ msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } /* if snapshot mode. */
}
static void vfe32_set_default_reg_values(void)
@@ -2654,6 +2721,13 @@
msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
}
+ } /* if raw snapshot mode. */
+ if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
+ (vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_VIDEO) &&
+ (vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+ vfe32_ctrl->vfeFrameId++;
+ CDBG("Skip the SOF notification when HFR enabled\n");
+ return;
}
vfe32_ctrl->vfeFrameId++;
vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_SOF_ACK);
@@ -2907,11 +2981,6 @@
}
}
-static void vfe32_process_stats_comb_irq(uint32_t *irqstatus)
-{
- return;
-}
-
static uint32_t vfe32_process_stats_irq_common(uint32_t statsNum,
uint32_t newAddr) {
@@ -2971,17 +3040,23 @@
case statsIhistNum: {
msgStats.id = MSG_ID_STATS_IHIST;
+ spin_lock_irqsave(&vfe32_ctrl->ihist_ack_lock, flags);
vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe32_ctrl->ihist_ack_lock, flags);
}
break;
case statsRsNum: {
msgStats.id = MSG_ID_STATS_RS;
+ spin_lock_irqsave(&vfe32_ctrl->rs_ack_lock, flags);
vfe32_ctrl->rsStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe32_ctrl->rs_ack_lock, flags);
}
break;
case statsCsNum: {
msgStats.id = MSG_ID_STATS_CS;
+ spin_lock_irqsave(&vfe32_ctrl->cs_ack_lock, flags);
vfe32_ctrl->csStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe32_ctrl->cs_ack_lock, flags);
}
break;
@@ -2997,6 +3072,30 @@
return;
}
+static void vfe_send_comp_stats_msg(uint32_t status_bits)
+{
+ struct msm_stats_buf msgStats;
+ uint32_t temp;
+
+ msgStats.frame_id = vfe32_ctrl->vfeFrameId;
+ msgStats.status_bits = status_bits;
+
+ msgStats.aec.buff = vfe32_ctrl->aecStatsControl.bufToRender;
+ msgStats.awb.buff = vfe32_ctrl->awbStatsControl.bufToRender;
+ msgStats.af.buff = vfe32_ctrl->afStatsControl.bufToRender;
+
+ msgStats.ihist.buff = vfe32_ctrl->ihistStatsControl.bufToRender;
+ msgStats.rs.buff = vfe32_ctrl->rsStatsControl.bufToRender;
+ msgStats.cs.buff = vfe32_ctrl->csStatsControl.bufToRender;
+
+ temp = msm_io_r(vfe32_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
+ msgStats.awb_ymin = (0xFF00 & temp) >> 8;
+
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
+ NOTIFY_VFE_MSG_COMP_STATS,
+ &msgStats);
+}
+
static void vfe32_process_stats_ae_irq(void)
{
unsigned long flags;
@@ -3105,6 +3204,126 @@
}
}
+static void vfe32_process_stats(uint32_t status_bits)
+{
+ unsigned long flags;
+ int32_t process_stats = false;
+ CDBG("%s, stats = 0x%x\n", __func__, status_bits);
+
+ spin_lock_irqsave(&vfe32_ctrl->comp_stats_ack_lock, flags);
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AEC) {
+ if (!vfe32_ctrl->aecStatsControl.ackPending) {
+ vfe32_ctrl->aecStatsControl.ackPending = TRUE;
+ vfe32_ctrl->aecStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsAeNum,
+ vfe32_ctrl->aecStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else{
+ vfe32_ctrl->aecStatsControl.bufToRender = 0;
+ vfe32_ctrl->aecStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe32_ctrl->aecStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AWB) {
+ if (!vfe32_ctrl->awbStatsControl.ackPending) {
+ vfe32_ctrl->awbStatsControl.ackPending = TRUE;
+ vfe32_ctrl->awbStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsAwbNum,
+ vfe32_ctrl->awbStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else{
+ vfe32_ctrl->awbStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->awbStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->awbStatsControl.bufToRender = 0;
+ }
+
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AF) {
+ if (!vfe32_ctrl->afStatsControl.ackPending) {
+ vfe32_ctrl->afStatsControl.ackPending = TRUE;
+ vfe32_ctrl->afStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsAfNum,
+ vfe32_ctrl->afStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->afStatsControl.bufToRender = 0;
+ vfe32_ctrl->afStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe32_ctrl->afStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_IHIST) {
+ if (!vfe32_ctrl->ihistStatsControl.ackPending) {
+ vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
+ vfe32_ctrl->ihistStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsIhistNum,
+ vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->ihistStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->ihistStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->ihistStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_RS) {
+ if (!vfe32_ctrl->rsStatsControl.ackPending) {
+ vfe32_ctrl->rsStatsControl.ackPending = TRUE;
+ vfe32_ctrl->rsStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsRsNum,
+ vfe32_ctrl->rsStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->rsStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->rsStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->rsStatsControl.bufToRender = 0;
+ }
+
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_CS) {
+ if (!vfe32_ctrl->csStatsControl.ackPending) {
+ vfe32_ctrl->csStatsControl.ackPending = TRUE;
+ vfe32_ctrl->csStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsCsNum,
+ vfe32_ctrl->csStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->csStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->csStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->csStatsControl.bufToRender = 0;
+ }
+
+ spin_unlock_irqrestore(&vfe32_ctrl->comp_stats_ack_lock, flags);
+ if (process_stats)
+ vfe_send_comp_stats_msg(status_bits);
+
+ return;
+}
+
+static void vfe32_process_stats_irq(uint32_t *irqstatus)
+{
+ uint32_t status_bits = VFE_COM_STATUS & *irqstatus;
+
+ if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
+ (vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+ CDBG("Skip the stats when HFR enabled\n");
+ return;
+ }
+
+ vfe32_process_stats(status_bits);
+ return;
+}
+
static void vfe32_do_tasklet(unsigned long data)
{
unsigned long flags;
@@ -3191,7 +3410,7 @@
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
CDBG("Stats composite irq occured.\n");
- vfe32_process_stats_comb_irq(
+ vfe32_process_stats_irq(
&qcmd->vfeInterruptStatus0);
}
} else {
@@ -3618,6 +3837,10 @@
spin_lock_init(&vfe32_ctrl->aec_ack_lock);
spin_lock_init(&vfe32_ctrl->awb_ack_lock);
spin_lock_init(&vfe32_ctrl->af_ack_lock);
+ spin_lock_init(&vfe32_ctrl->ihist_ack_lock);
+ spin_lock_init(&vfe32_ctrl->rs_ack_lock);
+ spin_lock_init(&vfe32_ctrl->cs_ack_lock);
+ spin_lock_init(&vfe32_ctrl->comp_stats_ack_lock);
spin_lock_init(&vfe32_ctrl->sd_notify_lock);
INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
@@ -3625,6 +3848,7 @@
vfe32_ctrl->update_rolloff = false;
vfe32_ctrl->update_la = false;
vfe32_ctrl->update_gamma = false;
+ vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
enable_irq(vfe32_ctrl->vfeirq->start);
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 1adfffd..62c3639 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -168,6 +168,9 @@
#define VFE_AF_PINGPONG_STATUS_BIT 0x100
#define VFE_AWB_PINGPONG_STATUS_BIT 0x200
+#define HFR_MODE_OFF 1
+#define VFE_FRAME_SKIP_PERIOD_MASK 0x0000001F /*bits 0 -4*/
+
enum VFE32_DMI_RAM_SEL {
NO_MEM_SELECTED = 0,
BLACK_LUT_RAM_BANK0 = 0x1,
@@ -220,7 +223,7 @@
#define V32_OUT_CLAMP_OFF 0x00000524
#define V32_OUT_CLAMP_LEN 8
-#define V32_OPERATION_CFG_LEN 32
+#define V32_OPERATION_CFG_LEN 36
#define V32_AXI_OUT_OFF 0x00000038
#define V32_AXI_OUT_LEN 216
@@ -778,6 +781,8 @@
#define VFE32_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<21)
#define VFE32_IMASK_AXI_ERROR (0x00000001<<22)
+#define VFE_COM_STATUS 0x000FE000
+
struct vfe32_output_path {
uint16_t output_mode; /* bitmask */
@@ -864,6 +869,7 @@
#define VFE_CLAMP_MIN 0x00000528
#define VFE_REALIGN_BUF 0x0000052C
#define VFE_STATS_CFG 0x00000530
+#define VFE_STATS_AWB_SGW_CFG 0x00000554
#define VFE_DMI_CFG 0x00000598
#define VFE_DMI_ADDR 0x0000059C
#define VFE_DMI_DATA_LO 0x000005A4
@@ -906,6 +912,10 @@
spinlock_t aec_ack_lock;
spinlock_t awb_ack_lock;
spinlock_t af_ack_lock;
+ spinlock_t ihist_ack_lock;
+ spinlock_t rs_ack_lock;
+ spinlock_t cs_ack_lock;
+ spinlock_t comp_stats_ack_lock;
uint32_t extlen;
void *extdata;
@@ -958,6 +968,10 @@
struct platform_device *pdev;
struct clk *vfe_clk[3];
spinlock_t sd_notify_lock;
+ uint32_t hfr_mode;
+ uint32_t frame_skip_cnt;
+ uint32_t frame_skip_pattern;
+ uint32_t snapshot_frame_cnt;
};
#define statsAeNum 0
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index a9b7bc6..047226e 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
obj-$(CONFIG_IMX074) += imx074_v4l2.o
obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
+obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
obj-$(CONFIG_OV2720) += ov2720.o
obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 2c296618..d0b4f1f 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -215,7 +215,7 @@
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
- PIX0, ISPIF_OFF_IMMEDIATELY));
+ PIX_0, ISPIF_OFF_IMMEDIATELY));
s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
msleep(30);
if (update_type == MSM_SENSOR_REG_INIT) {
@@ -244,7 +244,7 @@
output_settings[res].op_pixel_clk);
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
- PIX0, ISPIF_ON_FRAME_BOUNDARY));
+ PIX_0, ISPIF_ON_FRAME_BOUNDARY));
s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
msleep(30);
}
@@ -502,6 +502,7 @@
goto enable_clk_failed;
}
+ usleep_range(1000, 2000);
if (data->sensor_platform_info->ext_power_ctrl != NULL)
data->sensor_platform_info->ext_power_ctrl(1);
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
new file mode 100644
index 0000000..2177991
--- /dev/null
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -0,0 +1,695 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#define SENSOR_NAME "s5k3l1yx"
+#define PLATFORM_DRIVER_NAME "msm_camera_s5k3l1yx"
+
+DEFINE_MUTEX(s5k3l1yx_mut);
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl;
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_start_settings[] = {
+ {0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_stop_settings[] = {
+ {0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_groupon_settings[] = {
+ {0x104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_groupoff_settings[] = {
+ {0x104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_snap_settings[] = {
+ {0x0501, 0x00}, /* compression_algorithim_L(1d) */
+ {0x0112, 0x0A}, /* CCP_data_format_H */
+ {0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+ {0x0306, 0x00}, /* pll_multiplier */
+ {0x0307, 0xA5}, /* pll_multiplier */
+ {0x0202, 0x09}, /* coarse_integration_time */
+ {0x0203, 0x32}, /* coarse_integration_time */
+ {0x0340, 0x0B}, /* frame_length_lines */
+ {0x0341, 0xEC}, /* frame_length_lines */
+ {0x0342, 0x14}, /* line_length_pck */
+ {0x0343, 0xD8}, /* line_length_pck */
+ {0x0344, 0x00}, /* x_addr_start */
+ {0x0345, 0x08}, /* x_addr_start */
+ {0x0346, 0x00}, /* y_addr_start */
+ {0x0347, 0x00}, /* y_addr_start */
+ {0x0348, 0x0F}, /* x_addr_end */
+ {0x0349, 0xA7}, /* x_addr_end */
+ {0x034A, 0x0B}, /* y_addr_end */
+ {0x034B, 0xC7}, /* y_addr_end */
+ {0x034C, 0x0F}, /* x_output_size */
+ {0x034D, 0xA0}, /* x_output_size */
+ {0x034E, 0x0B}, /* y_output_size */
+ {0x034F, 0xC8}, /* y_output_size */
+ {0x0380, 0x00}, /* x_even_inc */
+ {0x0381, 0x01}, /* x_even_inc */
+ {0x0382, 0x00}, /* x_odd_inc */
+ {0x0383, 0x01}, /* x_odd_inc */
+ {0x0384, 0x00}, /* y_even_inc */
+ {0x0385, 0x01}, /* y_even_inc */
+ {0x0386, 0x00}, /* y_odd_inc */
+ {0x0387, 0x01}, /* y_odd_inc */
+ {0x0900, 0x00}, /* binning_mode */
+ {0x0901, 0x22}, /* binning_type */
+ {0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_prev_settings[] = {
+ {0x0501, 0x00}, /* compression_algorithim_L(1d) */
+ {0x0112, 0x0A}, /* CCP_data_format_H */
+ {0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+ {0x0306, 0x00}, /* pll_multiplier */
+ {0x0307, 0xA5}, /* pll_multiplier */
+ {0x0202, 0x06}, /* coarse_integration_time */
+ {0x0203, 0x00}, /* coarse_integration_time */
+ {0x0340, 0x09}, /* frame_length_lines */
+ {0x0341, 0x98}, /* frame_length_lines */
+ {0x0342, 0x11}, /* line_length_pck */
+ {0x0343, 0x80}, /* line_length_pck */
+ {0x0344, 0x00}, /* x_addr_start */
+ {0x0345, 0x18}, /* x_addr_start */
+ {0x0346, 0x00}, /* y_addr_start */
+ {0x0347, 0x00}, /* y_addr_start */
+ {0x0348, 0x0F}, /* x_addr_end */
+ {0x0349, 0x97}, /* x_addr_end */
+ {0x034A, 0x0B}, /* y_addr_end */
+ {0x034B, 0xC7}, /* y_addr_end */
+ {0x034C, 0x07}, /* x_output_size */
+ {0x034D, 0xC0}, /* x_output_size */
+ {0x034E, 0x05}, /* y_output_size */
+ {0x034F, 0xE4}, /* y_output_size */
+ {0x0380, 0x00}, /* x_even_inc */
+ {0x0381, 0x01}, /* x_even_inc */
+ {0x0382, 0x00}, /* x_odd_inc */
+ {0x0383, 0x03}, /* x_odd_inc */
+ {0x0384, 0x00}, /* y_even_inc */
+ {0x0385, 0x01}, /* y_even_inc */
+ {0x0386, 0x00}, /* y_odd_inc */
+ {0x0387, 0x03}, /* y_odd_inc */
+ {0x0900, 0x01}, /* binning_mode */
+ {0x0901, 0x22}, /* binning_type */
+ {0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_60fps_settings[] = {
+ {0x0501, 0x00}, /* compression_algorithim_L(1d) */
+ {0x0112, 0x0A}, /* CCP_data_format_H */
+ {0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+ {0x0306, 0x00}, /* pll_multiplier */
+ {0x0307, 0xA5}, /* pll_multiplier */
+ {0x0202, 0x02}, /* coarse_integration_time */
+ {0x0203, 0x1C}, /* coarse_integration_time */
+ {0x0340, 0x03}, /* frame_length_lines */
+ {0x0341, 0xE0}, /* frame_length_lines */
+ {0x0342, 0x14}, /* line_length_pck */
+ {0x0343, 0xD8}, /* line_length_pck */
+ {0x0344, 0x01}, /* x_addr_start */
+ {0x0345, 0x20}, /* x_addr_start */
+ {0x0346, 0x02}, /* y_addr_start */
+ {0x0347, 0x23}, /* y_addr_start */
+ {0x0348, 0x0E}, /* x_addr_end */
+ {0x0349, 0xA0}, /* x_addr_end */
+ {0x034A, 0x09}, /* y_addr_end */
+ {0x034B, 0xA4}, /* y_addr_end */
+ {0x034C, 0x03}, /* x_output_size */
+ {0x034D, 0x60}, /* x_output_size */
+ {0x034E, 0x01}, /* y_output_size */
+ {0x034F, 0xE0}, /* y_output_size */
+ {0x0380, 0x00}, /* x_even_inc */
+ {0x0381, 0x01}, /* x_even_inc */
+ {0x0382, 0x00}, /* x_odd_inc */
+ {0x0383, 0x07}, /* x_odd_inc */
+ {0x0384, 0x00}, /* y_even_inc */
+ {0x0385, 0x01}, /* y_even_inc */
+ {0x0386, 0x00}, /* y_odd_inc */
+ {0x0387, 0x07}, /* y_odd_inc */
+ {0x0900, 0x01}, /* binning_mode */
+ {0x0901, 0x44}, /* binning_type */
+ {0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_90fps_settings[] = {
+ {0x0501, 0x00}, /* compression_algorithim_L(1d) */
+ {0x0112, 0x0A}, /* CCP_data_format_H */
+ {0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+ {0x0306, 0x00}, /* pll_multiplier */
+ {0x0307, 0xA5}, /* pll_multiplier */
+ {0x0202, 0x02}, /* coarse_integration_time */
+ {0x0203, 0x1C}, /* coarse_integration_time */
+ {0x0340, 0x02}, /* frame_length_lines */
+ {0x0341, 0x98}, /* frame_length_lines */
+ {0x0342, 0x14}, /* line_length_pck */
+ {0x0343, 0xD8}, /* line_length_pck */
+ {0x0344, 0x01}, /* x_addr_start */
+ {0x0345, 0x20}, /* x_addr_start */
+ {0x0346, 0x02}, /* y_addr_start */
+ {0x0347, 0x23}, /* y_addr_start */
+ {0x0348, 0x0E}, /* x_addr_end */
+ {0x0349, 0xA0}, /* x_addr_end */
+ {0x034A, 0x09}, /* y_addr_end */
+ {0x034B, 0xA4}, /* y_addr_end */
+ {0x034C, 0x03}, /* x_output_size */
+ {0x034D, 0x60}, /* x_output_size */
+ {0x034E, 0x01}, /* y_output_size */
+ {0x034F, 0xE0}, /* y_output_size */
+ {0x0380, 0x00}, /* x_even_inc */
+ {0x0381, 0x01}, /* x_even_inc */
+ {0x0382, 0x00}, /* x_odd_inc */
+ {0x0383, 0x07}, /* x_odd_inc */
+ {0x0384, 0x00}, /* y_even_inc */
+ {0x0385, 0x01}, /* y_even_inc */
+ {0x0386, 0x00}, /* y_odd_inc */
+ {0x0387, 0x07}, /* y_odd_inc */
+ {0x0900, 0x01}, /* binning_mode */
+ {0x0901, 0x44}, /* binning_type */
+ {0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_video_120fps_settings[] = {
+ {0x0501, 0x00}, /* compression_algorithim_L(1d) */
+ {0x0112, 0x0A}, /* CCP_data_format_H */
+ {0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+ {0x0306, 0x00}, /* pll_multiplier */
+ {0x0307, 0xA5}, /* pll_multiplier */
+ {0x0202, 0x02}, /* coarse_integration_time */
+ {0x0203, 0x1C}, /* coarse_integration_time */
+ {0x0340, 0x02}, /* frame_length_lines */
+ {0x0341, 0x0D}, /* frame_length_lines */
+ {0x0342, 0x14}, /* line_length_pck */
+ {0x0343, 0xD8}, /* line_length_pck */
+ {0x0344, 0x01}, /* x_addr_start */
+ {0x0345, 0x20}, /* x_addr_start */
+ {0x0346, 0x02}, /* y_addr_start */
+ {0x0347, 0x23}, /* y_addr_start */
+ {0x0348, 0x0E}, /* x_addr_end */
+ {0x0349, 0xA0}, /* x_addr_end */
+ {0x034A, 0x09}, /* y_addr_end */
+ {0x034B, 0xA4}, /* y_addr_end */
+ {0x034C, 0x03}, /* x_output_size */
+ {0x034D, 0x60}, /* x_output_size */
+ {0x034E, 0x01}, /* y_output_size */
+ {0x034F, 0xE0}, /* y_output_size */
+ {0x0380, 0x00}, /* x_even_inc */
+ {0x0381, 0x01}, /* x_even_inc */
+ {0x0382, 0x00}, /* x_odd_inc */
+ {0x0383, 0x07}, /* x_odd_inc */
+ {0x0384, 0x00}, /* y_even_inc */
+ {0x0385, 0x01}, /* y_even_inc */
+ {0x0386, 0x00}, /* y_odd_inc */
+ {0x0387, 0x07}, /* y_odd_inc */
+ {0x0900, 0x01}, /* binning_mode */
+ {0x0901, 0x44}, /* binning_type */
+ {0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_dpcm_settings[] = {
+ {0x0501, 0x01}, /* compression_algorithim_L(1d) */
+ {0x0112, 0x0A}, /* CCP_data_format_H */
+ {0x0113, 0x08}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+ {0x0306, 0x00}, /* pll_multiplier */
+ {0x0307, 0xA0}, /* pll_multiplier */
+ {0x0202, 0x09}, /* coarse_integration_time */
+ {0x0203, 0x32}, /* coarse_integration_time */
+ {0x0340, 0x0B}, /* frame_length_lines */
+ {0x0341, 0xEC}, /* frame_length_lines */
+ {0x0342, 0x11}, /* line_length_pck */
+ {0x0343, 0x80}, /* line_length_pck */
+ {0x0344, 0x00}, /* x_addr_start */
+ {0x0345, 0x08}, /* x_addr_start */
+ {0x0346, 0x00}, /* y_addr_start */
+ {0x0347, 0x00}, /* y_addr_start */
+ {0x0348, 0x0F}, /* x_addr_end */
+ {0x0349, 0xA7}, /* x_addr_end */
+ {0x034A, 0x0B}, /* y_addr_end */
+ {0x034B, 0xC7}, /* y_addr_end */
+ {0x034C, 0x0F}, /* x_output_size */
+ {0x034D, 0xA0}, /* x_output_size */
+ {0x034E, 0x0B}, /* y_output_size */
+ {0x034F, 0xC8}, /* y_output_size */
+ {0x0380, 0x00}, /* x_even_inc */
+ {0x0381, 0x01}, /* x_even_inc */
+ {0x0382, 0x00}, /* x_odd_inc */
+ {0x0383, 0x01}, /* x_odd_inc */
+ {0x0384, 0x00}, /* y_even_inc */
+ {0x0385, 0x01}, /* y_even_inc */
+ {0x0386, 0x00}, /* y_odd_inc */
+ {0x0387, 0x01}, /* y_odd_inc */
+ {0x0900, 0x00}, /* binning_mode */
+ {0x0901, 0x22}, /* binning_type */
+ {0x0902, 0x01}, /* binning_weighting */
+};
+
+static struct msm_camera_i2c_reg_conf s5k3l1yx_recommend_settings[] = {
+ {0x0100, 0x00},
+ {0x0103, 0x01}, /* software_reset */
+ {0x0104, 0x00}, /* grouped_parameter_hold */
+ {0x0114, 0x03}, /* CSI_lane_mode, 4 lane setting */
+ {0x0120, 0x00}, /* gain_mode, global analogue gain*/
+ {0x0121, 0x00}, /* exposure_mode, global exposure */
+ {0x0136, 0x18}, /* Extclk_frequency_mhz */
+ {0x0137, 0x00}, /* Extclk_frequency_mhz */
+ {0x0200, 0x08}, /* fine_integration_time */
+ {0x0201, 0x88}, /* fine_integration_time */
+ {0x0204, 0x00}, /* analogue_gain_code_global */
+ {0x0205, 0x20}, /* analogue_gain_code_global */
+ {0x020E, 0x01}, /* digital_gain_greenR */
+ {0x020F, 0x00}, /* digital_gain_greenR */
+ {0x0210, 0x01}, /* digital_gain_red */
+ {0x0211, 0x00}, /* digital_gain_red */
+ {0x0212, 0x01}, /* digital_gain_blue */
+ {0x0213, 0x00}, /* digital_gain_blue */
+ {0x0214, 0x01}, /* digital_gain_greenB */
+ {0x0215, 0x00}, /* digital_gain_greenB */
+ {0x0300, 0x00}, /* vt_pix_clk_div */
+ {0x0301, 0x02}, /* vt_pix_clk_div */
+ {0x0302, 0x00}, /* vt_sys_clk_div */
+ {0x0303, 0x01}, /* vt_sys_clk_div */
+ {0x0304, 0x00}, /* pre_pll_clk_div */
+ {0x0305, 0x06}, /* pre_pll_clk_div */
+ {0x0308, 0x00}, /* op_pix_clk_div */
+ {0x0309, 0x02}, /* op_pix_clk_div */
+ {0x030A, 0x00}, /* op_sys_clk_div */
+ {0x030B, 0x01}, /* op_sys_clk_div */
+ {0x0800, 0x00}, /* tclk_post for D-PHY control */
+ {0x0801, 0x00}, /* ths_prepare for D-PHY control */
+ {0x0802, 0x00}, /* ths_zero_min for D-PHY control */
+ {0x0803, 0x00}, /* ths_trail for D-PHY control */
+ {0x0804, 0x00}, /* tclk_trail_min for D-PHY control */
+ {0x0805, 0x00}, /* tclk_prepare for D-PHY control */
+ {0x0806, 0x00}, /* tclk_zero_zero for D-PHY control */
+ {0x0807, 0x00}, /* tlpx for D-PHY control */
+ {0x0820, 0x02}, /* requested_link_bit_rate_mbps */
+ {0x0821, 0x94}, /* requested_link_bit_rate_mbps */
+ {0x0822, 0x00}, /* requested_link_bit_rate_mbps */
+ {0x0823, 0x00}, /* requested_link_bit_rate_mbps */
+ {0x3000, 0x0A},
+ {0x3001, 0xF7},
+ {0x3002, 0x0A},
+ {0x3003, 0xF7},
+ {0x3004, 0x08},
+ {0x3005, 0xF8},
+ {0x3006, 0x5B},
+ {0x3007, 0x73},
+ {0x3008, 0x49},
+ {0x3009, 0x0C},
+ {0x300A, 0xF8},
+ {0x300B, 0x4E},
+ {0x300C, 0x64},
+ {0x300D, 0x5C},
+ {0x300E, 0x71},
+ {0x300F, 0x0C},
+ {0x3010, 0x6A},
+ {0x3011, 0x14},
+ {0x3012, 0x14},
+ {0x3013, 0x0C},
+ {0x3014, 0x24},
+ {0x3015, 0x4F},
+ {0x3016, 0x86},
+ {0x3017, 0x0E},
+ {0x3018, 0x2C},
+ {0x3019, 0x30},
+ {0x301A, 0x31},
+ {0x301B, 0x32},
+ {0x301C, 0xFF},
+ {0x301D, 0x33},
+ {0x301E, 0x5C},
+ {0x301F, 0xFA},
+ {0x3020, 0x36},
+ {0x3021, 0x46},
+ {0x3022, 0x92},
+ {0x3023, 0xF5},
+ {0x3024, 0x6E},
+ {0x3025, 0x19},
+ {0x3026, 0x32},
+ {0x3027, 0x4B},
+ {0x3028, 0x04},
+ {0x3029, 0x50},
+ {0x302A, 0x0C},
+ {0x302B, 0x04},
+ {0x302C, 0xEF},
+ {0x302D, 0xC1},
+ {0x302E, 0x74},
+ {0x302F, 0x40},
+ {0x3030, 0x00},
+ {0x3031, 0x00},
+ {0x3032, 0x00},
+ {0x3033, 0x00},
+ {0x3034, 0x0F},
+ {0x3035, 0x01},
+ {0x3036, 0x00},
+ {0x3037, 0x00},
+ {0x3038, 0x88},
+ {0x3039, 0x98},
+ {0x303A, 0x1F},
+ {0x303B, 0x01},
+ {0x303C, 0x00},
+ {0x303D, 0x03},
+ {0x303E, 0x2F},
+ {0x303F, 0x09},
+ {0x3040, 0xFF},
+ {0x3041, 0x22},
+ {0x3042, 0x03},
+ {0x3043, 0x03},
+ {0x3044, 0x20},
+ {0x3045, 0x10},
+ {0x3046, 0x10},
+ {0x3047, 0x08},
+ {0x3048, 0x10},
+ {0x3049, 0x01},
+ {0x304A, 0x00},
+ {0x304B, 0x80},
+ {0x304C, 0x80},
+ {0x304D, 0x00},
+ {0x304E, 0x00},
+ {0x304F, 0x00},
+ {0x3051, 0x09},
+ {0x3052, 0xC4},
+ {0x305A, 0xE0},
+ {0x323D, 0x04},
+ {0x323E, 0x38},
+ {0x3305, 0xDD},
+ {0x3050, 0x01},
+ {0x3202, 0x01},
+ {0x3203, 0x01},
+ {0x3204, 0x01},
+ {0x3205, 0x01},
+ {0x3206, 0x01},
+ {0x3207, 0x01},
+ {0x320A, 0x05},
+ {0x320B, 0x20},
+ {0x3235, 0xB7},
+ {0x324C, 0x04},
+ {0x324A, 0x07},
+ {0x3902, 0x01},
+ {0x3915, 0x70},
+ {0x3916, 0x80},
+ {0x3A00, 0x01},
+ {0x3A06, 0x03},
+ {0x3B29, 0x01},
+ {0x3C11, 0x08},
+ {0x3C12, 0x7B},
+ {0x3C13, 0xC0},
+ {0x3C14, 0x70},
+ {0x3C15, 0x80},
+ {0x3C20, 0x00},
+ {0x3C23, 0x03},
+ {0x3C24, 0x00},
+ {0x3C50, 0x72},
+ {0x3C51, 0x85},
+ {0x3C53, 0x40},
+ {0x3C55, 0xA0},
+ {0x3D00, 0x00},
+ {0x3D01, 0x00},
+ {0x3D11, 0x01},
+ {0x3486, 0x05},
+ {0x3B35, 0x06},
+ {0x3A05, 0x01},
+ {0x3A07, 0x2B},
+ {0x3A09, 0x01},
+ {0x3940, 0xFF},
+ {0x3300, 0x00},
+ {0x3900, 0xFF},
+ {0x3914, 0x08},
+ {0x3A01, 0x0F},
+ {0x3A02, 0xA0},
+ {0x3A03, 0x0B},
+ {0x3A04, 0xC8},
+ {0x3701, 0x00},
+ {0x3702, 0x00},
+ {0x3703, 0x00},
+ {0x3704, 0x00},
+ {0x0101, 0x00}, /* image_orientation, mirror & flip off*/
+ {0x0105, 0x01}, /* mask_corrupted_frames */
+ {0x0110, 0x00}, /* CSI-2_channel_identifier */
+ {0x3942, 0x01}, /* [0] 1:mipi, 0:pvi */
+ {0x0B00, 0x00},
+};
+
+static struct v4l2_subdev_info s5k3l1yx_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array s5k3l1yx_init_conf[] = {
+ {&s5k3l1yx_recommend_settings[0],
+ ARRAY_SIZE(s5k3l1yx_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array s5k3l1yx_confs[] = {
+ {&s5k3l1yx_snap_settings[0],
+ ARRAY_SIZE(s5k3l1yx_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&s5k3l1yx_prev_settings[0],
+ ARRAY_SIZE(s5k3l1yx_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&s5k3l1yx_video_60fps_settings[0],
+ ARRAY_SIZE(s5k3l1yx_video_60fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&s5k3l1yx_video_90fps_settings[0],
+ ARRAY_SIZE(s5k3l1yx_video_90fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&s5k3l1yx_video_120fps_settings[0],
+ ARRAY_SIZE(s5k3l1yx_video_120fps_settings), 0,
+ MSM_CAMERA_I2C_BYTE_DATA},
+ {&s5k3l1yx_dpcm_settings[0],
+ ARRAY_SIZE(s5k3l1yx_dpcm_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t s5k3l1yx_dimensions[] = {
+ /* 20 fps snapshot */
+ {
+ .x_output = 4000,
+ .y_output = 3016,
+ .line_length_pclk = 5336,
+ .frame_length_lines = 3052,
+ .vt_pixel_clk = 330000000,
+ .op_pixel_clk = 320000000,
+ .binning_factor = 1,
+ },
+ /* 30 fps preview */
+ {
+ .x_output = 1984,
+ .y_output = 1508,
+ .line_length_pclk = 4480,
+ .frame_length_lines = 2456,
+ .vt_pixel_clk = 330000000,
+ .op_pixel_clk = 320000000,
+ .binning_factor = 1,
+ },
+ /* 60 fps video */
+ {
+ .x_output = 864,
+ .y_output = 480,
+ .line_length_pclk = 5336,
+ .frame_length_lines = 992,
+ .vt_pixel_clk = 330000000,
+ .op_pixel_clk = 320000000,
+ .binning_factor = 1,
+ },
+ /* 90 fps video */
+ {
+ .x_output = 864,
+ .y_output = 480,
+ .line_length_pclk = 5336,
+ .frame_length_lines = 664,
+ .vt_pixel_clk = 330000000,
+ .op_pixel_clk = 320000000,
+ .binning_factor = 1,
+ },
+ /* 120 fps video */
+ {
+ .x_output = 864,
+ .y_output = 480,
+ .line_length_pclk = 5336,
+ .frame_length_lines = 525,
+ .vt_pixel_clk = 330000000,
+ .op_pixel_clk = 320000000,
+ .binning_factor = 1,
+ },
+ /* 24 fps snapshot */
+ {
+ .x_output = 4000,
+ .y_output = 3016,
+ .line_length_pclk = 4480,
+ .frame_length_lines = 3052,
+ .vt_pixel_clk = 330000000,
+ .op_pixel_clk = 320000000,
+ .binning_factor = 1,
+ },
+};
+
+static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_cfg[] = {
+ {0, CSI_RAW10, CSI_DECODE_10BIT},
+};
+
+static struct msm_camera_csi2_params s5k3l1yx_csi_params = {
+ .csid_params = {
+ .lane_assign = 0xe4,
+ .lane_cnt = 4,
+ .lut_params = {
+ .num_cid = ARRAY_SIZE(s5k3l1yx_cid_cfg),
+ .vc_cfg = s5k3l1yx_cid_cfg,
+ },
+ },
+ .csiphy_params = {
+ .lane_cnt = 4,
+ .settle_cnt = 0x1B,
+ },
+};
+
+static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_dpcm_cfg[] = {
+ {0, CSI_RAW8, CSI_DECODE_DPCM_10_8_10},
+};
+
+static struct msm_camera_csi2_params s5k3l1yx_csi_dpcm_params = {
+ .csid_params = {
+ .lane_assign = 0xe4,
+ .lane_cnt = 4,
+ .lut_params = {
+ .num_cid = ARRAY_SIZE(s5k3l1yx_cid_dpcm_cfg),
+ .vc_cfg = s5k3l1yx_cid_dpcm_cfg,
+ },
+ },
+ .csiphy_params = {
+ .lane_cnt = 4,
+ .settle_cnt = 0x1B,
+ },
+};
+
+static struct msm_camera_csi2_params *s5k3l1yx_csi_params_array[] = {
+ &s5k3l1yx_csi_params,
+ &s5k3l1yx_csi_params,
+ &s5k3l1yx_csi_params,
+ &s5k3l1yx_csi_params,
+ &s5k3l1yx_csi_params,
+ &s5k3l1yx_csi_dpcm_params,
+};
+
+static struct msm_sensor_output_reg_addr_t s5k3l1yx_reg_addr = {
+ .x_output = 0x34C,
+ .y_output = 0x34E,
+ .line_length_pclk = 0x342,
+ .frame_length_lines = 0x340,
+};
+
+static struct msm_sensor_id_info_t s5k3l1yx_id_info = {
+ .sensor_id_reg_addr = 0x0,
+ .sensor_id = 0x3121,
+};
+
+static struct msm_sensor_exp_gain_info_t s5k3l1yx_exp_gain_info = {
+ .coarse_int_time_addr = 0x202,
+ .global_gain_addr = 0x204,
+ .vert_offset = 8,
+};
+
+static const struct i2c_device_id s5k3l1yx_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&s5k3l1yx_s_ctrl},
+ { }
+};
+
+static struct i2c_driver s5k3l1yx_i2c_driver = {
+ .id_table = s5k3l1yx_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client s5k3l1yx_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ return i2c_add_driver(&s5k3l1yx_i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops s5k3l1yx_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops s5k3l1yx_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops s5k3l1yx_subdev_ops = {
+ .core = &s5k3l1yx_subdev_core_ops,
+ .video = &s5k3l1yx_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t s5k3l1yx_func_tbl = {
+ .sensor_start_stream = msm_sensor_start_stream,
+ .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = msm_sensor_set_fps,
+ .sensor_write_exp_gain = msm_sensor_write_exp_gain1,
+ .sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
+ .sensor_setting = msm_sensor_setting,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = msm_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t s5k3l1yx_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .start_stream_conf = s5k3l1yx_start_settings,
+ .start_stream_conf_size = ARRAY_SIZE(s5k3l1yx_start_settings),
+ .stop_stream_conf = s5k3l1yx_stop_settings,
+ .stop_stream_conf_size = ARRAY_SIZE(s5k3l1yx_stop_settings),
+ .group_hold_on_conf = s5k3l1yx_groupon_settings,
+ .group_hold_on_conf_size = ARRAY_SIZE(s5k3l1yx_groupon_settings),
+ .group_hold_off_conf = s5k3l1yx_groupoff_settings,
+ .group_hold_off_conf_size =
+ ARRAY_SIZE(s5k3l1yx_groupoff_settings),
+ .init_settings = &s5k3l1yx_init_conf[0],
+ .init_size = ARRAY_SIZE(s5k3l1yx_init_conf),
+ .mode_settings = &s5k3l1yx_confs[0],
+ .output_settings = &s5k3l1yx_dimensions[0],
+ .num_conf = ARRAY_SIZE(s5k3l1yx_confs),
+};
+
+static struct msm_sensor_ctrl_t s5k3l1yx_s_ctrl = {
+ .msm_sensor_reg = &s5k3l1yx_regs,
+ .sensor_i2c_client = &s5k3l1yx_sensor_i2c_client,
+ .sensor_i2c_addr = 0x6E,
+ .sensor_output_reg_addr = &s5k3l1yx_reg_addr,
+ .sensor_id_info = &s5k3l1yx_id_info,
+ .sensor_exp_gain_info = &s5k3l1yx_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csi_params = &s5k3l1yx_csi_params_array[0],
+ .msm_sensor_mutex = &s5k3l1yx_mut,
+ .sensor_i2c_driver = &s5k3l1yx_i2c_driver,
+ .sensor_v4l2_subdev_info = s5k3l1yx_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(s5k3l1yx_subdev_info),
+ .sensor_v4l2_subdev_ops = &s5k3l1yx_subdev_ops,
+ .func_tbl = &s5k3l1yx_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Samsung 12MP Bayer sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 30192d9..c8fcf5f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -69,7 +69,7 @@
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-obj-$(CONFIG_WCD9310_CODEC) += wcd9310-core.o wcd9310-irq.o
+obj-$(CONFIG_WCD9310_CODEC) += wcd9310-core.o wcd9310-irq.o wcd9310-slimslave.o
ifeq ($(CONFIG_SA1100_ASSABET),y)
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index ceb4210..ac57418 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -268,6 +268,11 @@
.id = -1,
};
+static struct mfd_cell leds_cell __devinitdata = {
+ .name = PM8XXX_LEDS_DEV_NAME,
+ .id = -1,
+};
+
static struct mfd_cell debugfs_cell __devinitdata = {
.name = "pm8xxx-debug",
.id = 0,
@@ -501,6 +506,16 @@
}
}
+ if (pdata->leds_pdata) {
+ leds_cell.platform_data = pdata->leds_pdata;
+ leds_cell.pdata_size = sizeof(struct pm8xxx_led_platform_data);
+ ret = mfd_add_devices(pmic->dev, 0, &leds_cell, 1, NULL, 0);
+ if (ret) {
+ pr_err("Failed to add leds subdevice ret=%d\n", ret);
+ goto bail;
+ }
+ }
+
if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
ret = pm8038_add_regulators(pdata, pmic, irq_base);
if (ret) {
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 84eadef..87abcda 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -14,8 +14,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mfd/core.h>
+#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
#include <linux/mfd/pm8xxx/pm8921.h>
-#include <linux/mfd/wcd9310/core.h>
#include <linux/mfd/wcd9310/pdata.h>
#include <linux/mfd/wcd9310/registers.h>
#include <linux/delay.h>
@@ -370,6 +370,13 @@
mutex_init(&tabla->io_lock);
mutex_init(&tabla->xfer_lock);
+
+ mutex_init(&tabla->pm_lock);
+ tabla->wlock_holders = 0;
+ tabla->pm_state = TABLA_PM_SLEEPABLE;
+ init_waitqueue_head(&tabla->pm_wq);
+ wake_lock_init(&tabla->wlock, WAKE_LOCK_IDLE, "wcd9310-irq");
+
dev_set_drvdata(tabla->dev, tabla);
tabla_bring_up(tabla);
@@ -397,19 +404,22 @@
tabla_irq_exit(tabla);
err:
tabla_bring_down(tabla);
+ wake_lock_destroy(&tabla->wlock);
+ mutex_destroy(&tabla->pm_lock);
mutex_destroy(&tabla->io_lock);
mutex_destroy(&tabla->xfer_lock);
return ret;
}
+
static void tabla_device_exit(struct tabla *tabla)
{
tabla_irq_exit(tabla);
tabla_bring_down(tabla);
tabla_free_reset(tabla);
+ mutex_destroy(&tabla->pm_lock);
+ wake_lock_destroy(&tabla->wlock);
mutex_destroy(&tabla->io_lock);
mutex_destroy(&tabla->xfer_lock);
- slim_remove_device(tabla->slim_slave);
- kfree(tabla);
}
@@ -707,13 +717,13 @@
}
int tabla_i2c_read(struct tabla *tabla, unsigned short reg,
- int bytes, void *dest, bool interface_reg)
+ int bytes, void *dest, bool interface_reg)
{
return tabla_i2c_read_device(reg, bytes, dest);
}
int tabla_i2c_write(struct tabla *tabla, unsigned short reg,
- int bytes, void *src, bool interface_reg)
+ int bytes, void *src, bool interface_reg)
{
return tabla_i2c_write_device(reg, src, bytes);
}
@@ -799,7 +809,13 @@
static int __devexit tabla_i2c_remove(struct i2c_client *client)
{
+ struct tabla *tabla;
+
pr_debug("exit\n");
+ tabla = dev_get_drvdata(&client->dev);
+ tabla_device_exit(tabla);
+ tabla_disable_supplies(tabla);
+ kfree(tabla);
return 0;
}
@@ -905,7 +921,7 @@
pr_err("%s: error, initializing device failed\n", __func__);
goto err_slim_add;
}
-
+ tabla_init_slimslave(tabla, tabla_pgd_la);
#ifdef CONFIG_DEBUG_FS
debugTabla = tabla;
@@ -935,6 +951,7 @@
err:
return ret;
}
+
static int tabla_slim_remove(struct slim_device *pdev)
{
struct tabla *tabla;
@@ -946,16 +963,106 @@
#endif
tabla = slim_get_devicedata(pdev);
+ tabla_deinit_slimslave(tabla);
tabla_device_exit(tabla);
tabla_disable_supplies(tabla);
+ slim_remove_device(tabla->slim_slave);
kfree(tabla);
return 0;
}
+
+static int tabla_resume(struct tabla *tabla)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ mutex_lock(&tabla->pm_lock);
+ if (tabla->pm_state == TABLA_PM_ASLEEP) {
+ pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+ tabla->pm_state, tabla->wlock_holders);
+ tabla->pm_state = TABLA_PM_SLEEPABLE;
+ } else {
+ pr_warn("%s: system is already awake, state %d wlock %d\n",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ }
+ mutex_unlock(&tabla->pm_lock);
+ wake_up_all(&tabla->pm_wq);
+
+ return ret;
+}
+
+static int tabla_slim_resume(struct slim_device *sldev)
+{
+ struct tabla *tabla = slim_get_devicedata(sldev);
+ return tabla_resume(tabla);
+}
+
+static int tabla_i2c_resume(struct i2c_client *i2cdev)
+{
+ struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
+ return tabla_resume(tabla);
+}
+
+static int tabla_suspend(struct tabla *tabla, pm_message_t pmesg)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ /* wake_lock() can be called after this suspend chain call started.
+ * thus suspend can be called while wlock is being held */
+ mutex_lock(&tabla->pm_lock);
+ if (tabla->pm_state == TABLA_PM_SLEEPABLE) {
+ pr_debug("%s: suspending system, state %d, wlock %d\n",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ tabla->pm_state = TABLA_PM_ASLEEP;
+ } else if (tabla->pm_state == TABLA_PM_AWAKE) {
+ /* unlock to wait for pm_state == TABLA_PM_SLEEPABLE
+ * then set to TABLA_PM_ASLEEP */
+ pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ mutex_unlock(&tabla->pm_lock);
+ if (!(wait_event_timeout(tabla->pm_wq,
+ tabla_pm_cmpxchg(tabla,
+ TABLA_PM_SLEEPABLE,
+ TABLA_PM_ASLEEP) ==
+ TABLA_PM_SLEEPABLE,
+ HZ))) {
+ pr_debug("%s: suspend failed state %d, wlock %d\n",
+ __func__, tabla->pm_state,
+ tabla->wlock_holders);
+ ret = -EBUSY;
+ } else {
+ pr_debug("%s: done, state %d, wlock %d\n", __func__,
+ tabla->pm_state, tabla->wlock_holders);
+ }
+ mutex_lock(&tabla->pm_lock);
+ } else if (tabla->pm_state == TABLA_PM_ASLEEP) {
+ pr_warn("%s: system is already suspended, state %d, wlock %dn",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ }
+ mutex_unlock(&tabla->pm_lock);
+
+ return ret;
+}
+
+static int tabla_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
+{
+ struct tabla *tabla = slim_get_devicedata(sldev);
+ return tabla_suspend(tabla, pmesg);
+}
+
+static int tabla_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
+{
+ struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
+ return tabla_suspend(tabla, pmesg);
+}
+
static const struct slim_device_id slimtest_id[] = {
{"tabla-slim", 0},
{}
};
+
static struct slim_driver tabla_slim_driver = {
.driver = {
.name = "tabla-slim",
@@ -964,6 +1071,8 @@
.probe = tabla_slim_probe,
.remove = tabla_slim_remove,
.id_table = slimtest_id,
+ .resume = tabla_slim_resume,
+ .suspend = tabla_slim_suspend,
};
static const struct slim_device_id slimtest2x_id[] = {
@@ -979,6 +1088,8 @@
.probe = tabla_slim_probe,
.remove = tabla_slim_remove,
.id_table = slimtest2x_id,
+ .resume = tabla_slim_resume,
+ .suspend = tabla_slim_suspend,
};
#define TABLA_I2C_TOP_LEVEL 0
@@ -996,13 +1107,15 @@
MODULE_DEVICE_TABLE(i2c, tabla_id_table);
static struct i2c_driver tabla_i2c_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "tabla-i2c-core",
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tabla-i2c-core",
},
- .id_table = tabla_id_table,
- .probe = tabla_i2c_probe,
- .remove = __devexit_p(tabla_i2c_remove),
+ .id_table = tabla_id_table,
+ .probe = tabla_i2c_probe,
+ .remove = __devexit_p(tabla_i2c_remove),
+ .resume = tabla_i2c_resume,
+ .suspend = tabla_i2c_suspend,
};
static int __init tabla_init(void)
diff --git a/drivers/mfd/wcd9310-irq.c b/drivers/mfd/wcd9310-irq.c
index fef1323..c6a9c23 100644
--- a/drivers/mfd/wcd9310-irq.c
+++ b/drivers/mfd/wcd9310-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,7 @@
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/sched.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wcd9310/core.h>
@@ -83,6 +84,60 @@
.irq_enable = tabla_irq_enable,
};
+enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
+ enum tabla_pm_state n)
+{
+ enum tabla_pm_state old;
+ mutex_lock(&tabla->pm_lock);
+ old = tabla->pm_state;
+ if (old == o)
+ tabla->pm_state = n;
+ mutex_unlock(&tabla->pm_lock);
+ return old;
+}
+EXPORT_SYMBOL_GPL(tabla_pm_cmpxchg);
+
+void tabla_lock_sleep(struct tabla *tabla)
+{
+ enum tabla_pm_state os;
+
+ /* tabla_{lock/unlock}_sleep will be called by tabla_irq_thread
+ * and its subroutines only motly.
+ * but btn0_lpress_fn is not tabla_irq_thread's subroutine and
+ * it can race with tabla_irq_thread.
+ * so need to embrace wlock_holders with mutex.
+ */
+ mutex_lock(&tabla->pm_lock);
+ if (tabla->wlock_holders++ == 0)
+ wake_lock(&tabla->wlock);
+ mutex_unlock(&tabla->pm_lock);
+ while (!wait_event_timeout(tabla->pm_wq,
+ ((os = tabla_pm_cmpxchg(tabla, TABLA_PM_SLEEPABLE,
+ TABLA_PM_AWAKE)) ==
+ TABLA_PM_SLEEPABLE ||
+ (os == TABLA_PM_AWAKE)),
+ 5 * HZ)) {
+ pr_err("%s: system didn't resume within 5000ms, state %d, "
+ "wlock %d\n", __func__, tabla->pm_state,
+ tabla->wlock_holders);
+ WARN_ON_ONCE(1);
+ }
+ wake_up_all(&tabla->pm_wq);
+}
+EXPORT_SYMBOL_GPL(tabla_lock_sleep);
+
+void tabla_unlock_sleep(struct tabla *tabla)
+{
+ mutex_lock(&tabla->pm_lock);
+ if (--tabla->wlock_holders == 0) {
+ tabla->pm_state = TABLA_PM_SLEEPABLE;
+ wake_unlock(&tabla->wlock);
+ }
+ mutex_unlock(&tabla->pm_lock);
+ wake_up_all(&tabla->pm_wq);
+}
+EXPORT_SYMBOL_GPL(tabla_unlock_sleep);
+
static irqreturn_t tabla_irq_thread(int irq, void *data)
{
int ret;
@@ -90,11 +145,13 @@
u8 status[TABLA_NUM_IRQ_REGS];
unsigned int i;
+ tabla_lock_sleep(tabla);
ret = tabla_bulk_read(tabla, TABLA_A_INTR_STATUS0,
TABLA_NUM_IRQ_REGS, status);
if (ret < 0) {
dev_err(tabla->dev, "Failed to read interrupt status: %d\n",
ret);
+ tabla_unlock_sleep(tabla);
return IRQ_NONE;
}
/* Apply masking */
@@ -127,6 +184,7 @@
break;
}
}
+ tabla_unlock_sleep(tabla);
return IRQ_HANDLED;
}
diff --git a/drivers/mfd/wcd9310-slimslave.c b/drivers/mfd/wcd9310-slimslave.c
new file mode 100644
index 0000000..dd586fa
--- /dev/null
+++ b/drivers/mfd/wcd9310-slimslave.c
@@ -0,0 +1,522 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
+
+struct tabla_slim_sch_rx {
+ u32 sph;
+ u32 ch_num;
+ u16 ch_h;
+ u16 grph;
+};
+
+struct tabla_slim_sch_tx {
+ u32 sph;
+ u32 ch_num;
+ u16 ch_h;
+ u16 grph;
+};
+
+struct tabla_slim_sch {
+ struct tabla_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
+ struct tabla_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
+};
+
+static struct tabla_slim_sch sh_ch;
+
+static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la);
+static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la);
+static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab);
+static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab);
+
+int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la)
+{
+ int ret = 0;
+
+ ret = tabla_alloc_slim_sh_ch_rx(tabla, tabla_pgd_la);
+ if (ret) {
+ pr_err("%s: Failed to alloc rx slimbus shared channels\n",
+ __func__);
+ goto rx_err;
+ }
+ ret = tabla_alloc_slim_sh_ch_tx(tabla, tabla_pgd_la);
+ if (ret) {
+ pr_err("%s: Failed to alloc tx slimbus shared channels\n",
+ __func__);
+ goto tx_err;
+ }
+ return 0;
+tx_err:
+ tabla_dealloc_slim_sh_ch_rx(tabla);
+rx_err:
+ return ret;
+}
+
+
+int tabla_deinit_slimslave(struct tabla *tabla)
+{
+ int ret = 0;
+ ret = tabla_dealloc_slim_sh_ch_rx(tabla);
+ if (ret < 0) {
+ pr_err("%s: fail to dealloc rx slim ports\n", __func__);
+ goto err;
+ }
+ ret = tabla_dealloc_slim_sh_ch_tx(tabla);
+ if (ret < 0) {
+ pr_err("%s: fail to dealloc tx slim ports\n", __func__);
+ goto err;
+ }
+err:
+ return ret;
+}
+
+int tabla_get_channel(struct tabla *tabla,
+ unsigned int *rx_ch,
+ unsigned int *tx_ch)
+{
+ int ch_idx = 0;
+ struct tabla_slim_sch_rx *rx = sh_ch.rx;
+ struct tabla_slim_sch_tx *tx = sh_ch.tx;
+
+ for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++)
+ rx_ch[ch_idx] = rx[ch_idx].ch_num;
+ for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++)
+ tx_ch[ch_idx] = tx[ch_idx].ch_num;
+ return 0;
+}
+
+static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la)
+{
+ int ret = 0;
+ u8 ch_idx ;
+ u16 slave_port_id = 0;
+ struct tabla_slim_sch_rx *rx = sh_ch.rx;
+
+ /* DSP requires channel number to be between 128 and 255. For RX port
+ * use channel numbers from 138 to 144, for TX port
+ * use channel numbers from 128 to 137
+ */
+ pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+ for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++) {
+ slave_port_id = (ch_idx + 1 +
+ SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS);
+ rx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
+ ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+ &rx[ch_idx].sph, SLIM_SINK);
+ if (ret < 0) {
+ pr_err("%s: slave port failure id[%d] ret[%d]\n",
+ __func__, slave_port_id, ret);
+ goto err;
+ }
+
+ ret = slim_query_ch(tabla->slim, rx[ch_idx].ch_num,
+ &rx[ch_idx].ch_h);
+ if (ret < 0) {
+ pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
+ __func__, rx[ch_idx].ch_num, ret);
+ goto err;
+ }
+ }
+err:
+ return ret;
+}
+
+static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la)
+{
+ int ret = 0;
+ u8 ch_idx ;
+ struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ u16 slave_port_id = 0;
+
+ pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+ /* DSP requires channel number to be between 128 and 255. For RX port
+ * use channel numbers from 138 to 144, for TX port
+ * use channel numbers from 128 to 137
+ */
+ for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++) {
+ slave_port_id = ch_idx;
+ tx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
+ ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+ &tx[ch_idx].sph, SLIM_SRC);
+ if (ret < 0) {
+ pr_err("%s: slave port failure id[%d] ret[%d]\n",
+ __func__, slave_port_id, ret);
+ goto err;
+ }
+ ret = slim_query_ch(tabla->slim, tx[ch_idx].ch_num,
+ &tx[ch_idx].ch_h);
+ if (ret < 0) {
+ pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
+ __func__, tx[ch_idx].ch_num, ret);
+ goto err;
+ }
+ }
+err:
+ return ret;
+}
+
+static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab)
+{
+ int idx = 0;
+ int ret = 0;
+ struct tabla_slim_sch_rx *rx = sh_ch.rx;
+ /* slim_dealloc_ch */
+ for (idx = 0; idx < SLIM_MAX_RX_PORTS; idx++) {
+ ret = slim_dealloc_ch(tab->slim, rx[idx].ch_h);
+ if (ret < 0) {
+ pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
+ __func__, ret, rx[idx].ch_h);
+ }
+ }
+ memset(sh_ch.rx, 0, sizeof(sh_ch.rx));
+ return ret;
+}
+
+static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab)
+{
+ int idx = 0;
+ int ret = 0;
+ struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ /* slim_dealloc_ch */
+ for (idx = 0; idx < SLIM_MAX_TX_PORTS; idx++) {
+ ret = slim_dealloc_ch(tab->slim, tx[idx].ch_h);
+ if (ret < 0) {
+ pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
+ __func__, ret, tx[idx].ch_h);
+ }
+ }
+ memset(sh_ch.tx, 0, sizeof(sh_ch.tx));
+ return ret;
+}
+
+/* Enable slimbus slave device for RX path */
+int tabla_cfg_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+ unsigned int ch_cnt, unsigned int rate)
+{
+ u8 i = 0;
+ u16 grph;
+ u32 sph[SLIM_MAX_RX_PORTS] = {0};
+ u16 ch_h[SLIM_MAX_RX_PORTS] = {0};
+ u16 slave_port_id;
+ u8 payload_rx = 0, wm_payload = 0;
+ int ret, idx = 0;
+ unsigned short multi_chan_cfg_reg_addr;
+ struct tabla_slim_sch_rx *rx = sh_ch.rx;
+ struct slim_ch prop;
+
+ /* Configure slave interface device */
+ pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
+
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM -
+ SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+ ch_h[i] = rx[idx].ch_h;
+ sph[i] = rx[idx].sph;
+ slave_port_id = idx + 1;
+ if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS) ||
+ (slave_port_id == 0)) {
+ pr_err("Slimbus: invalid slave port id: %d",
+ slave_port_id);
+ ret = -EINVAL;
+ goto err;
+ }
+ slave_port_id += SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS;
+ /* look for the valid port range and chose the
+ * payload accordingly
+ */
+ if ((slave_port_id >
+ SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) &&
+ (slave_port_id <
+ SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID)) {
+ payload_rx = payload_rx |
+ (1 <<
+ (slave_port_id -
+ SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID));
+ } else {
+ ret = -EINVAL;
+ goto err;
+ }
+ multi_chan_cfg_reg_addr =
+ SB_PGD_RX_PORT_MULTI_CHANNEL_0(slave_port_id);
+ /* write to interface device */
+ ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+ payload_rx);
+ if (ret < 0) {
+ pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+ __func__,
+ multi_chan_cfg_reg_addr,
+ payload_rx, ret);
+ goto err;
+ }
+ /* configure the slave port for water mark and enable*/
+ wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
+ SLAVE_PORT_WATER_MARK_SHIFT) +
+ SLAVE_PORT_ENABLE;
+ ret = tabla_interface_reg_write(tab,
+ SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
+ wm_payload);
+ if (ret < 0) {
+ pr_err("%s:watermark set failure for port[%d] ret[%d]",
+ __func__, slave_port_id, ret);
+ }
+ }
+
+ /* slim_define_ch api */
+ prop.prot = SLIM_AUTO_ISO;
+ prop.baser = SLIM_RATE_4000HZ;
+ prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
+ prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
+ prop.ratem = (rate/4000);
+ prop.sampleszbits = 16;
+
+ ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+ true, &grph);
+ if (ret < 0) {
+ pr_err("%s: slim_define_ch failed ret[%d]\n",
+ __func__, ret);
+ goto err;
+ }
+ for (i = 0; i < ch_cnt; i++) {
+ ret = slim_connect_sink(tab->slim, &sph[i],
+ 1, ch_h[i]);
+ if (ret < 0) {
+ pr_err("%s: slim_connect_sink failed ret[%d]\n",
+ __func__, ret);
+ goto err_close_slim_sch;
+ }
+ }
+ /* slim_control_ch */
+ ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+ true);
+ if (ret < 0) {
+ pr_err("%s: slim_control_ch failed ret[%d]\n",
+ __func__, ret);
+ goto err_close_slim_sch;
+ }
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM -
+ SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+ rx[idx].grph = grph;
+ }
+ return 0;
+
+err_close_slim_sch:
+ /* release all acquired handles */
+ tabla_close_slim_sch_rx(tab, ch_num, ch_cnt);
+err:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_rx);
+
+/* Enable slimbus slave device for RX path */
+int tabla_cfg_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+ unsigned int ch_cnt, unsigned int rate)
+{
+ u8 i = 0;
+ u8 payload_tx_0 = 0, payload_tx_1 = 0, wm_payload = 0;
+ u16 grph;
+ u32 sph[SLIM_MAX_TX_PORTS] = {0};
+ u16 ch_h[SLIM_MAX_TX_PORTS] = {0};
+ u16 idx = 0, slave_port_id;
+ int ret = 0;
+ unsigned short multi_chan_cfg_reg_addr;
+
+ struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ struct slim_ch prop;
+
+ pr_debug("%s: ch_cnt[%d] rate[%d]\n", __func__, ch_cnt, rate);
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM);
+ ch_h[i] = tx[idx].ch_h;
+ sph[i] = tx[idx].sph;
+ slave_port_id = idx ;
+ if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) ||
+ (slave_port_id == 0)) {
+ pr_err("SLIMbus: invalid slave port id: %d",
+ slave_port_id);
+ ret = -EINVAL;
+ goto err;
+ }
+ /* look for the valid port range and chose the
+ * payload accordingly
+ */
+ if (slave_port_id <=
+ SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID) {
+ payload_tx_0 = payload_tx_0 | (1 << slave_port_id);
+ } else if (slave_port_id <
+ SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) {
+ payload_tx_1 = payload_tx_1 |
+ (1 <<
+ (slave_port_id -
+ SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID));
+ } else {
+ ret = -EINVAL;
+ goto err;
+ }
+ multi_chan_cfg_reg_addr =
+ SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
+ /* write to interface device */
+ ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+ payload_tx_0);
+ if (ret < 0) {
+ pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+ __func__,
+ multi_chan_cfg_reg_addr,
+ payload_tx_0, ret);
+ goto err;
+ }
+ multi_chan_cfg_reg_addr =
+ SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
+ /* ports 8,9 */
+ ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+ payload_tx_1);
+ if (ret < 0) {
+ pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
+ __func__,
+ multi_chan_cfg_reg_addr,
+ payload_tx_1, ret);
+ goto err;
+ }
+ /* configure the slave port for water mark and enable*/
+ wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
+ SLAVE_PORT_WATER_MARK_SHIFT) +
+ SLAVE_PORT_ENABLE;
+ ret = tabla_interface_reg_write(tab,
+ SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
+ wm_payload);
+ if (ret < 0) {
+ pr_err("%s:watermark set failure for port[%d] ret[%d]",
+ __func__,
+ slave_port_id, ret);
+ }
+ }
+
+ /* slim_define_ch api */
+ prop.prot = SLIM_AUTO_ISO;
+ prop.baser = SLIM_RATE_4000HZ;
+ prop.dataf = SLIM_CH_DATAF_NOT_DEFINED;
+ prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
+ prop.ratem = (rate/4000);
+ prop.sampleszbits = 16;
+ ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+ true, &grph);
+ if (ret < 0) {
+ pr_err("%s: slim_define_ch failed ret[%d]\n",
+ __func__, ret);
+ goto err;
+ }
+ for (i = 0; i < ch_cnt; i++) {
+ ret = slim_connect_src(tab->slim, sph[i],
+ ch_h[i]);
+ if (ret < 0) {
+ pr_err("%s: slim_connect_src failed ret[%d]\n",
+ __func__, ret);
+ goto err;
+ }
+ }
+ /* slim_control_ch */
+ ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+ true);
+ if (ret < 0) {
+ pr_err("%s: slim_control_ch failed ret[%d]\n",
+ __func__, ret);
+ goto err;
+ }
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM);
+ tx[idx].grph = grph;
+ }
+ return 0;
+err:
+ /* release all acquired handles */
+ tabla_close_slim_sch_tx(tab, ch_num, ch_cnt);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_tx);
+
+int tabla_close_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+ unsigned int ch_cnt)
+{
+ u16 grph = 0;
+ u32 sph[SLIM_MAX_RX_PORTS] = {0};
+ int i = 0 , idx = 0;
+ int ret = 0;
+ struct tabla_slim_sch_rx *rx = sh_ch.rx;
+
+ pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM -
+ SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+ sph[i] = rx[idx].sph;
+ grph = rx[idx].grph;
+ }
+
+ /* slim_disconnect_port */
+ ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+ if (ret < 0) {
+ pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+ __func__, ret);
+ }
+ /* slim_control_ch (REMOVE) */
+ ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+ if (ret < 0) {
+ pr_err("%s: slim_control_ch failed ret[%d]\n",
+ __func__, ret);
+ goto err;
+ }
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM -
+ SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+ rx[idx].grph = 0;
+ }
+err:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_close_slim_sch_rx);
+
+int tabla_close_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+ unsigned int ch_cnt)
+{
+ u16 grph = 0;
+ u32 sph[SLIM_MAX_TX_PORTS] = {0};
+ int ret = 0;
+ int i = 0 , idx = 0;
+ struct tabla_slim_sch_tx *tx = sh_ch.tx;
+
+ pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM);
+ sph[i] = tx[idx].sph;
+ grph = tx[idx].grph;
+ }
+ /* slim_disconnect_port */
+ ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+ if (ret < 0) {
+ pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+ __func__, ret);
+ }
+ /* slim_control_ch (REMOVE) */
+ ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+ if (ret < 0) {
+ pr_err("%s: slim_control_ch failed ret[%d]\n",
+ __func__, ret);
+ goto err;
+ }
+ for (i = 0; i < ch_cnt; i++) {
+ idx = (ch_num[i] - BASE_CH_NUM);
+ tx[idx].grph = 0;
+ }
+err:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tabla_close_slim_sch_tx);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 8f42e5b..3ae639e 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1002,6 +1002,12 @@
}
}
+ /* Clear CDR_EN bit for write operations */
+ if (host->tuning_needed && cmd->mrq->data &&
+ (cmd->mrq->data->flags & MMC_DATA_WRITE))
+ writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG) &
+ ~MCI_CDR_EN), host->base + MCI_DLL_CONFIG);
+
if ((cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
*c |= MCI_CPSM_PROGENA;
host->prog_enable = 1;
@@ -2876,22 +2882,21 @@
* Select the 3/4 of the range and configure the DLL with the
* selected DLL clock output phase.
*/
-
static u8 find_most_appropriate_phase(struct msmsdcc_host *host,
u8 *phase_table, u8 total_phases)
{
- u8 ret, temp;
- u8 ranges[16][16] = { {0}, {0} };
+ u8 ret, ranges[16][16] = { {0}, {0} };
u8 phases_per_row[16] = {0};
int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
- int cnt;
+ int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
+ bool phase_0_found = false, phase_15_found = false;
- for (cnt = 0; cnt <= total_phases; cnt++) {
+ for (cnt = 0; cnt < total_phases; cnt++) {
ranges[row_index][col_index] = phase_table[cnt];
phases_per_row[row_index] += 1;
col_index++;
- if ((cnt + 1) > total_phases) {
+ if ((cnt + 1) == total_phases) {
continue;
/* check if next phase in phase_table is consecutive or not */
} else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) {
@@ -2900,15 +2905,50 @@
}
}
- for (cnt = 0; cnt <= total_phases; cnt++) {
+ /* Check if phase-0 is present in first valid window? */
+ if (!ranges[0][0]) {
+ phase_0_found = true;
+ phase_0_raw_index = 0;
+ /* Check if cycle exist between 2 valid windows */
+ for (cnt = 1; cnt <= row_index; cnt++) {
+ if (phases_per_row[cnt]) {
+ for (i = 0; i <= phases_per_row[cnt]; i++) {
+ if (ranges[cnt][i] == 15) {
+ phase_15_found = true;
+ phase_15_raw_index = cnt;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* If 2 valid windows form cycle then merge them as single window */
+ if (phase_0_found && phase_15_found) {
+ /* number of phases in raw where phase 0 is present */
+ u8 phases_0 = phases_per_row[phase_0_raw_index];
+ /* number of phases in raw where phase 15 is present */
+ u8 phases_15 = phases_per_row[phase_15_raw_index];
+
+ cnt = 0;
+ for (i = phases_15; i < (phases_15 + phases_0); i++) {
+ ranges[phase_15_raw_index][i] =
+ ranges[phase_0_raw_index][cnt];
+ cnt++;
+ }
+ phases_per_row[phase_0_raw_index] = 0;
+ phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
+ }
+
+ for (cnt = 0; cnt <= row_index; cnt++) {
if (phases_per_row[cnt] > curr_max) {
curr_max = phases_per_row[cnt];
selected_row_index = cnt;
}
}
- temp = ((curr_max * 3) / 4);
- ret = ranges[selected_row_index][temp];
+ i = ((curr_max * 3) / 4) - 1;
+ ret = ranges[selected_row_index][i];
return ret;
}
@@ -2981,11 +3021,12 @@
!memcmp(data_buf, cmd19_tuning_block, 64)) {
/* tuning is successful with this tuning point */
tuned_phases[tuned_phase_cnt++] = phase;
+ pr_debug("%s: %s: found good phase = %d\n",
+ mmc_hostname(mmc), __func__, phase);
}
} while (++phase < 16);
if (tuned_phase_cnt) {
- tuned_phase_cnt--;
phase = find_most_appropriate_phase(host, tuned_phases,
tuned_phase_cnt);
/*
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5c62769..b83e871 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -283,6 +283,14 @@
---help---
A driver for Qualcomm WLAN SDIO Libra chipset.
+config ATH6K_LEGACY
+ tristate "QCA AR6003 wlan SDIO driver"
+ depends on MMC_MSM && WLAN
+ select WIRELESS_EXT
+ select WEXT_PRIV
+ ---help---
+ This module adds support for wireless adapters based on QCA AR6003 chipset running over SDIO.
+
config WCNSS_CORE
tristate "Qualcomm WCNSS CORE driver"
depends on ARCH_MSM8960
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 7217434..d99f13a 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -41,12 +41,53 @@
struct resource *rx_irq_res;
struct resource *gpios_5wire;
const struct dev_pm_ops *pm_ops;
- int triggered;
- int smd_channel_ready;
+ int triggered;
+ int smd_channel_ready;
+ unsigned int serial_number;
struct wcnss_wlan_config wlan_config;
struct delayed_work wcnss_work;
} *penv = NULL;
+static ssize_t wcnss_serial_number_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (!penv)
+ return -ENODEV;
+
+ return scnprintf(buf, PAGE_SIZE, "%08X\n", penv->serial_number);
+}
+
+static ssize_t wcnss_serial_number_store(struct device *dev,
+ struct device_attribute *attr, const char * buf, size_t count)
+{
+ unsigned int value;
+
+ if (!penv)
+ return -ENODEV;
+
+ if (sscanf(buf, "%08X", &value) != 1)
+ return -EINVAL;
+
+ penv->serial_number = value;
+ return count;
+}
+
+static DEVICE_ATTR(serial_number, S_IRUSR | S_IWUSR,
+ wcnss_serial_number_show, wcnss_serial_number_store);
+
+static int wcnss_create_sysfs(struct device *dev)
+{
+ if (!dev)
+ return -ENODEV;
+ return device_create_file(dev, &dev_attr_serial_number);
+}
+
+static void wcnss_remove_sysfs(struct device *dev)
+{
+ if (dev)
+ device_remove_file(dev, &dev_attr_serial_number);
+}
+
static void wcnss_post_bootup(struct work_struct *work)
{
pr_info("%s: Cancel APPS vote for Iris & Riva\n", __func__);
@@ -189,6 +230,14 @@
}
EXPORT_SYMBOL(wcnss_wlan_unregister_pm_ops);
+unsigned int wcnss_get_serial_number(void)
+{
+ if (penv)
+ return penv->serial_number;
+ return 0;
+}
+EXPORT_SYMBOL(wcnss_get_serial_number);
+
static int wcnss_wlan_suspend(struct device *dev)
{
if (penv && dev && (dev == &penv->pdev->dev) &&
@@ -272,8 +321,14 @@
goto fail_res;
}
+ /* register sysfs entries */
+ ret = wcnss_create_sysfs(&pdev->dev);
+ if (ret)
+ goto fail_sysfs;
+
return 0;
+fail_sysfs:
fail_res:
if (penv->pil)
pil_put(penv->pil);
@@ -360,6 +415,7 @@
static int __devexit
wcnss_wlan_remove(struct platform_device *pdev)
{
+ wcnss_remove_sysfs(&pdev->dev);
return 0;
}
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 2e80692..93de829 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1893,7 +1893,7 @@
INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
/* begin calibration only on chips > 2.0 */
if (chip->revision >= PM8XXX_REVISION_8921_2p0)
- calibrate_ccadc_work(&(chip->calib_ccadc_work.work));
+ schedule_delayed_work(&chip->calib_ccadc_work, 0);
/* initial hkadc calibration */
schedule_work(&chip->calib_hkadc_work);
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 17cf53a..c95fd93 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -209,7 +209,7 @@
return rc;
}
if ((reg & (START_CONV_BIT | EOC_CONV_BIT)) != EOC_CONV_BIT)
- msleep(60);
+ msleep(20);
else
break;
}
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 6c5b380..02d1c39 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -75,6 +75,8 @@
#define SAT_MSG_VER 0x1
#define SAT_MSG_PROT 0x1
#define MSM_SAT_SUCCSS 0x20
+#define MSM_MAX_NSATS 2
+#define MSM_MAX_SATCH 32
#define QC_MFGID_LSB 0x2
#define QC_MFGID_MSB 0x17
@@ -225,7 +227,7 @@
int err;
int ee;
struct completion *wr_comp;
- struct msm_slim_sat *satd;
+ struct msm_slim_sat *satd[MSM_MAX_NSATS];
struct msm_slim_endp pipes[7];
struct msm_slim_sps_bam bam;
struct msm_slim_endp rx_msgq;
@@ -240,6 +242,14 @@
bool reconf_busy;
bool chan_active;
enum msm_ctrl_state state;
+ int nsats;
+};
+
+struct msm_sat_chan {
+ u8 chan;
+ u16 chanh;
+ int req_rem;
+ int req_def;
};
struct msm_slim_sat {
@@ -248,7 +258,7 @@
struct workqueue_struct *wq;
struct work_struct wd;
u8 sat_msgs[SAT_CONCUR_MSG][40];
- u16 *satch;
+ struct msm_sat_chan *satch;
u8 nsatch;
bool sent_capability;
bool pending_reconf;
@@ -258,6 +268,8 @@
spinlock_t lock;
};
+static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev);
+
static int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len)
{
spin_lock(&dev->rx_lock);
@@ -364,6 +376,18 @@
#endif
}
+static struct msm_slim_sat *addr_to_sat(struct msm_slim_ctrl *dev, u8 laddr)
+{
+ struct msm_slim_sat *sat = NULL;
+ int i = 0;
+ while (!sat && i < dev->nsats) {
+ if (laddr == dev->satd[i]->satcl.laddr)
+ sat = dev->satd[i];
+ i++;
+ }
+ return sat;
+}
+
static irqreturn_t msm_slim_interrupt(int irq, void *d)
{
struct msm_slim_ctrl *dev = d;
@@ -403,8 +427,13 @@
dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
if (mt == SLIM_MSG_MT_DEST_REFERRED_USER ||
mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
- struct msm_slim_sat *sat = dev->satd;
- msm_sat_enqueue(sat, rx_buf, len);
+ u8 laddr = (u8)((rx_buf[0] >> 16) & 0xFF);
+ struct msm_slim_sat *sat = addr_to_sat(dev, laddr);
+ if (sat)
+ msm_sat_enqueue(sat, rx_buf, len);
+ else
+ dev_err(dev->dev, "unknown sat:%d message",
+ laddr);
writel_relaxed(MGR_INT_RX_MSG_RCVD,
dev->base + MGR_INT_CLR);
/*
@@ -412,37 +441,21 @@
* queuing work
*/
mb();
- queue_work(sat->wq, &sat->wd);
+ if (sat)
+ queue_work(sat->wq, &sat->wd);
} else if (mt == SLIM_MSG_MT_CORE &&
mc == SLIM_MSG_MC_REPORT_PRESENT) {
u8 e_addr[6];
msm_get_eaddr(e_addr, rx_buf);
- if (msm_is_sat_dev(e_addr)) {
- /*
- * Consider possibility that this device may
- * be reporting more than once?
- */
- struct msm_slim_sat *sat = dev->satd;
- msm_sat_enqueue(sat, rx_buf, len);
- writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
- MGR_INT_CLR);
- /*
- * Guarantee that CLR bit write goes through
- * before queuing work
- */
- mb();
- queue_work(sat->wq, &sat->wd);
- } else {
- msm_slim_rx_enqueue(dev, rx_buf, len);
- writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
- MGR_INT_CLR);
- /*
- * Guarantee that CLR bit write goes through
- * before signalling completion
- */
- mb();
- complete(&dev->rx_msgq_notify);
- }
+ msm_slim_rx_enqueue(dev, rx_buf, len);
+ writel_relaxed(MGR_INT_RX_MSG_RCVD, dev->base +
+ MGR_INT_CLR);
+ /*
+ * Guarantee that CLR bit write goes through
+ * before signalling completion
+ */
+ mb();
+ complete(&dev->rx_msgq_notify);
} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
mc == SLIM_MSG_MC_REPLY_VALUE) {
msm_slim_rx_enqueue(dev, rx_buf, len);
@@ -959,18 +972,67 @@
int i;
int ret = 0;
if (mc == SLIM_USR_MC_CHAN_CTRL) {
- u16 chanh = sat->satch[buf[5]];
+ for (i = 0; i < sat->nsatch; i++) {
+ if (buf[5] == sat->satch[i].chan)
+ break;
+ }
+ if (i >= sat->nsatch)
+ return -ENOTCONN;
oper = ((buf[3] & 0xC0) >> 6);
/* part of grp. activating/removing 1 will take care of rest */
- ret = slim_control_ch(&sat->satcl, chanh, oper, false);
+ ret = slim_control_ch(&sat->satcl, sat->satch[i].chanh, oper,
+ false);
+ if (!ret) {
+ for (i = 5; i < len; i++) {
+ int j;
+ for (j = 0; j < sat->nsatch; j++) {
+ if (buf[i] == sat->satch[j].chan) {
+ if (oper == SLIM_CH_REMOVE)
+ sat->satch[j].req_rem++;
+ else
+ sat->satch[j].req_def++;
+ break;
+ }
+ }
+ }
+ }
} else {
u16 chh[40];
struct slim_ch prop;
u32 exp;
u8 coeff, cc;
u8 prrate = buf[6];
- for (i = 8; i < len; i++)
- chh[i-8] = sat->satch[buf[i]];
+ if (len <= 8)
+ return -EINVAL;
+ for (i = 8; i < len; i++) {
+ int j = 0;
+ for (j = 0; j < sat->nsatch; j++) {
+ if (sat->satch[j].chan == buf[i]) {
+ chh[i - 8] = sat->satch[j].chanh;
+ break;
+ }
+ }
+ if (j < sat->nsatch) {
+ u16 dummy;
+ ret = slim_query_ch(&sat->satcl, buf[i],
+ &dummy);
+ if (ret)
+ return ret;
+ if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
+ sat->satch[j].req_def++;
+ continue;
+ }
+ if (sat->nsatch >= MSM_MAX_SATCH)
+ return -EXFULL;
+ ret = slim_query_ch(&sat->satcl, buf[i], &chh[i - 8]);
+ if (ret)
+ return ret;
+ sat->satch[j].chan = buf[i];
+ sat->satch[j].chanh = chh[i - 8];
+ if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
+ sat->satch[j].req_def++;
+ sat->nsatch++;
+ }
prop.dataf = (enum slim_ch_dataf)((buf[3] & 0xE0) >> 5);
prop.auxf = (enum slim_ch_auxf)((buf[4] & 0xC0) >> 5);
prop.baser = SLIM_RATE_4000HZ;
@@ -986,17 +1048,18 @@
prop.ratem = cc * (1 << exp);
if (i > 9)
ret = slim_define_ch(&sat->satcl, &prop, chh, len - 8,
- true, &sat->satch[buf[8]]);
+ true, &chh[0]);
else
ret = slim_define_ch(&sat->satcl, &prop,
- &sat->satch[buf[8]], 1, false,
- NULL);
+ &chh[0], 1, false, NULL);
dev_dbg(dev->dev, "define sat grp returned:%d", ret);
+ if (ret)
+ return ret;
/* part of group so activating 1 will take care of rest */
if (mc == SLIM_USR_MC_DEF_ACT_CHAN)
ret = slim_control_ch(&sat->satcl,
- sat->satch[buf[8]],
+ chh[0],
SLIM_CH_ACTIVATE, false);
}
return ret;
@@ -1029,6 +1092,18 @@
laddr == (QC_MSM_DEVS - 1))
pm_runtime_enable(dev->dev);
+ if (!ret && msm_is_sat_dev(e_addr)) {
+ struct msm_slim_sat *sat = addr_to_sat(dev,
+ laddr);
+ if (!sat)
+ sat = msm_slim_alloc_sat(dev);
+ if (!sat)
+ return;
+
+ sat->satcl.laddr = laddr;
+ msm_sat_enqueue(sat, (u32 *)buf, len);
+ queue_work(sat->wq, &sat->wd);
+ }
} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
mc == SLIM_MSG_MC_REPLY_VALUE) {
u8 tid = buf[3];
@@ -1064,7 +1139,6 @@
while ((msm_sat_dequeue(sat, buf)) != -ENODATA) {
struct slim_msg_txn txn;
- int i;
u8 len, mc, mt;
u32 bw_sl;
int ret = 0;
@@ -1072,6 +1146,7 @@
bool gen_ack = false;
u8 tid;
u8 wbuf[8];
+ int i;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
txn.dt = SLIM_MSG_DEST_LOGICALADDR;
txn.ec = 0;
@@ -1112,20 +1187,23 @@
continue;
}
/* send a Manager capability msg */
- if (sat->sent_capability)
- continue;
+ if (sat->sent_capability) {
+ if (mt == SLIM_MSG_MT_CORE)
+ goto send_capability;
+ else
+ continue;
+ }
ret = slim_add_device(&dev->ctrl, &sat->satcl);
if (ret) {
dev_err(dev->dev,
"Satellite-init failed");
continue;
}
- /* Satellite owns first 21 channels */
- sat->satch = kzalloc(21 * sizeof(u16), GFP_KERNEL);
- sat->nsatch = 20;
- /* alloc all sat chans */
- for (i = 0; i < 21; i++)
- slim_alloc_ch(&sat->satcl, &sat->satch[i]);
+ /* Satellite-channels */
+ sat->satch = kzalloc(MSM_MAX_SATCH *
+ sizeof(struct msm_sat_chan),
+ GFP_KERNEL);
+send_capability:
txn.mc = SLIM_USR_MC_MASTER_CAPABILITY;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
txn.la = sat->satcl.laddr;
@@ -1176,6 +1254,20 @@
tid = buf[3];
gen_ack = true;
ret = slim_reconfigure_now(&sat->satcl);
+ for (i = 0; i < sat->nsatch; i++) {
+ struct msm_sat_chan *sch = &sat->satch[i];
+ if (sch->req_rem) {
+ if (!ret)
+ slim_dealloc_ch(&sat->satcl,
+ sch->chanh);
+ sch->req_rem--;
+ } else if (sch->req_def) {
+ if (ret)
+ slim_dealloc_ch(&sat->satcl,
+ sch->chanh);
+ sch->req_def--;
+ }
+ }
if (sat->pending_reconf) {
msm_slim_put_ctrl(dev);
sat->pending_reconf = false;
@@ -1243,6 +1335,44 @@
}
}
+static struct msm_slim_sat *msm_slim_alloc_sat(struct msm_slim_ctrl *dev)
+{
+ struct msm_slim_sat *sat;
+ char *name;
+ if (dev->nsats >= MSM_MAX_NSATS)
+ return NULL;
+
+ sat = kzalloc(sizeof(struct msm_slim_sat), GFP_KERNEL);
+ if (!sat) {
+ dev_err(dev->dev, "no memory for satellite");
+ return NULL;
+ }
+ name = kzalloc(SLIMBUS_NAME_SIZE, GFP_KERNEL);
+ if (!name) {
+ dev_err(dev->dev, "no memory for satellite name");
+ kfree(sat);
+ return NULL;
+ }
+ dev->satd[dev->nsats] = sat;
+ sat->dev = dev;
+ snprintf(name, SLIMBUS_NAME_SIZE, "msm_sat%d", dev->nsats);
+ sat->satcl.name = name;
+ spin_lock_init(&sat->lock);
+ INIT_WORK(&sat->wd, slim_sat_rxprocess);
+ sat->wq = create_singlethread_workqueue(sat->satcl.name);
+ if (!sat->wq) {
+ kfree(name);
+ kfree(sat);
+ return NULL;
+ }
+ /*
+ * Both sats will be allocated from RX thread and RX thread will
+ * process messages sequentially. No synchronization necessary
+ */
+ dev->nsats++;
+ return sat;
+}
+
static void
msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
{
@@ -1375,18 +1505,13 @@
mc = (buffer[0] >> 8) & 0xff;
dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
if (mt == SLIM_MSG_MT_DEST_REFERRED_USER ||
- mt == SLIM_MSG_MT_SRC_REFERRED_USER)
- sat = dev->satd;
-
+ mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
+ u8 laddr;
+ laddr = (u8)((buffer[0] >> 16) & 0xff);
+ sat = addr_to_sat(dev, laddr);
+ }
} else if ((index * 4) >= msg_len) {
index = 0;
- if (mt == SLIM_MSG_MT_CORE &&
- mc == SLIM_MSG_MC_REPORT_PRESENT) {
- u8 e_addr[6];
- msm_get_eaddr(e_addr, buffer);
- if (msm_is_sat_dev(e_addr))
- sat = dev->satd;
- }
if (sat) {
msm_sat_enqueue(sat, buffer, msg_len);
queue_work(sat->wq, &sat->wd);
@@ -1737,11 +1862,6 @@
}
- dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
- if (!dev->rclk) {
- dev_err(dev->dev, "slimbus clock not found");
- goto err_clk_get_failed;
- }
dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
dev->framer.superfreq =
dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
@@ -1756,21 +1876,24 @@
goto err_request_irq_failed;
}
- dev->satd = kzalloc(sizeof(struct msm_slim_sat), GFP_KERNEL);
- if (!dev->satd) {
- ret = -ENOMEM;
- goto err_sat_failed;
+ msm_slim_prg_slew(pdev, dev);
+
+ /* Register with framework before enabling frame, clock */
+ ret = slim_add_numbered_controller(&dev->ctrl);
+ if (ret) {
+ dev_err(dev->dev, "error adding controller\n");
+ goto err_ctrl_failed;
}
- msm_slim_prg_slew(pdev, dev);
+
+ dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
+ if (!dev->rclk) {
+ dev_err(dev->dev, "slimbus clock not found");
+ goto err_clk_get_failed;
+ }
clk_set_rate(dev->rclk, SLIM_ROOT_FREQ);
clk_enable(dev->rclk);
- dev->satd->dev = dev;
- dev->satd->satcl.name = "msm_sat_dev";
- spin_lock_init(&dev->satd->lock);
- INIT_WORK(&dev->satd->wd, slim_sat_rxprocess);
- dev->satd->wq = create_singlethread_workqueue("msm_slim_sat");
/* Component register initialization */
writel_relaxed(1, dev->base + COMP_CFG);
writel_relaxed((EE_MGR_RSC_GRP | EE_NGD_2 | EE_NGD_1),
@@ -1796,13 +1919,6 @@
*/
wmb();
- /* Register with framework before enabling frame, clock */
- ret = slim_add_numbered_controller(&dev->ctrl);
- if (ret) {
- dev_err(dev->dev, "error adding controller\n");
- goto err_ctrl_failed;
- }
-
/* Framer register initialization */
writel_relaxed((0xA << REF_CLK_GEAR) | (0xA << CLK_GEAR) |
(1 << ROOT_FREQ) | (1 << FRM_ACTIVE) | 1,
@@ -1855,13 +1971,9 @@
err_ctrl_failed:
writel_relaxed(0, dev->base + COMP_CFG);
- kfree(dev->satd);
-err_sat_failed:
- free_irq(dev->irq, dev);
-err_request_irq_failed:
- clk_disable(dev->rclk);
- clk_put(dev->rclk);
err_clk_get_failed:
+ kfree(dev->satd);
+err_request_irq_failed:
msm_slim_sps_exit(dev);
err_sps_init_failed:
iounmap(dev->bam.base);
@@ -1882,13 +1994,20 @@
struct resource *bam_mem;
struct resource *slim_mem;
struct resource *slew_mem = dev->slew_mem;
- struct msm_slim_sat *sat = dev->satd;
- slim_remove_device(&sat->satcl);
+ int i;
+ for (i = 0; i < dev->nsats; i++) {
+ struct msm_slim_sat *sat = dev->satd[i];
+ int j;
+ for (j = 0; j < sat->nsatch; j++)
+ slim_dealloc_ch(&sat->satcl, sat->satch[j].chanh);
+ slim_remove_device(&sat->satcl);
+ kfree(sat->satch);
+ destroy_workqueue(sat->wq);
+ kfree(sat->satcl.name);
+ kfree(sat);
+ }
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
- kfree(sat->satch);
- destroy_workqueue(sat->wq);
- kfree(sat);
free_irq(dev->irq, dev);
slim_del_controller(&dev->ctrl);
clk_put(dev->rclk);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 84cb3f5..3aa4553 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -3,7 +3,7 @@
* MSM 7k High speed uart driver
*
* Copyright (c) 2008 Google Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
* Modified: Nick Pelly <npelly@google.com>
*
* All source code in this file is licensed under the following license
@@ -656,7 +656,6 @@
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
spin_lock_irqsave(&uport->lock, flags);
- clk_enable(msm_uport->clk);
/*
* Disable Rx channel of UARTDM
@@ -764,9 +763,7 @@
}
msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
- /* calling other hardware component here clk_disable API. */
mb();
- clk_disable(msm_uport->clk);
spin_unlock_irqrestore(&uport->lock, flags);
}
@@ -778,16 +775,11 @@
{
unsigned int data;
unsigned int ret = 0;
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
- clk_enable(msm_uport->clk);
data = msm_hs_read(uport, UARTDM_SR_ADDR);
if (data & UARTDM_SR_TXEMT_BMSK)
ret = TIOCSER_TEMT;
- clk_disable(msm_uport->clk);
-
return ret;
}
EXPORT_SYMBOL(msm_hs_tx_empty);
@@ -817,8 +809,6 @@
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
unsigned int data;
- clk_enable(msm_uport->clk);
-
/* disable dlink */
data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
data &= ~UARTDM_RX_DM_EN_BMSK;
@@ -835,8 +825,6 @@
}
if (msm_uport->rx.flush != FLUSH_SHUTDOWN)
msm_uport->rx.flush = FLUSH_STOP;
-
- clk_disable(msm_uport->clk);
}
/* Transmit the next chunk of data */
@@ -1011,7 +999,6 @@
spin_lock_irqsave(&uport->lock, flags);
- clk_enable(msm_uport->clk);
msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
/* overflow is not connect to data in a FIFO */
@@ -1085,7 +1072,6 @@
schedule_delayed_work(&msm_uport->rx.flip_insert_work
, msecs_to_jiffies(RETRY_TIMEOUT));
}
- clk_disable(msm_uport->clk);
/* release wakelock in 500ms, not immediately, because higher layers
* don't always take wakelocks when they should */
wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
@@ -1100,15 +1086,11 @@
{
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- clk_enable(msm_uport->clk);
-
if (msm_uport->tx.tx_ready_int_en == 0) {
msm_uport->tx.tx_ready_int_en = 1;
if (msm_uport->tx.dma_in_flight == 0)
msm_hs_submit_tx_locked(uport);
}
-
- clk_disable(msm_uport->clk);
}
/*
@@ -1138,14 +1120,12 @@
tlet_ptr, struct msm_hs_port, tx.tlet);
spin_lock_irqsave(&(msm_uport->uport.lock), flags);
- clk_enable(msm_uport->clk);
msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK;
msm_hs_write(&(msm_uport->uport), UARTDM_IMR_ADDR, msm_uport->imr_reg);
/* Calling clk API. Hence mb() requires. */
mb();
- clk_disable(msm_uport->clk);
spin_unlock_irqrestore(&(msm_uport->uport.lock), flags);
}
@@ -1198,9 +1178,6 @@
{
unsigned int set_rts;
unsigned int data;
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
- clk_enable(msm_uport->clk);
/* RTS is active low */
set_rts = TIOCM_RTS & mctrl ? 0 : 1;
@@ -1217,9 +1194,7 @@
data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
msm_hs_write(uport, UARTDM_MR1_ADDR, data);
}
- /* Calling CLOCK API. Hence mb() requires. */
mb();
- clk_disable(msm_uport->clk);
}
void msm_hs_set_mctrl(struct uart_port *uport,
@@ -1238,16 +1213,11 @@
{
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- clk_enable(msm_uport->clk);
-
/* Enable DELTA_CTS Interrupt */
msm_uport->imr_reg |= UARTDM_ISR_DELTA_CTS_BMSK;
msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
- /* Calling CLOCK API. Hence mb() requires here. */
mb();
- clk_disable(msm_uport->clk);
-
}
/*
@@ -1259,14 +1229,10 @@
static void msm_hs_break_ctl(struct uart_port *uport, int ctl)
{
unsigned long flags;
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
spin_lock_irqsave(&uport->lock, flags);
- clk_enable(msm_uport->clk);
msm_hs_write(uport, UARTDM_CR_ADDR, ctl ? START_BREAK : STOP_BREAK);
- /* Calling CLOCK API. Hence mb() requires here. */
mb();
- clk_disable(msm_uport->clk);
spin_unlock_irqrestore(&uport->lock, flags);
}
@@ -1295,18 +1261,12 @@
/* Handle CTS changes (Called from interrupt handler) */
static void msm_hs_handle_delta_cts_locked(struct uart_port *uport)
{
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
- clk_enable(msm_uport->clk);
-
/* clear interrupt */
msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
/* Calling CLOCK API. Hence mb() requires here. */
mb();
uport->icount.cts++;
- clk_disable(msm_uport->clk);
-
/* clear the IOCTL TIOCMIWAIT if called */
wake_up_interruptible(&uport->state->port.delta_msr_wait);
}
@@ -1999,8 +1959,6 @@
tasklet_kill(&msm_uport->rx.tlet);
cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
- clk_enable(msm_uport->clk);
-
pm_runtime_disable(uport->dev);
pm_runtime_set_suspended(uport->dev);
@@ -2018,7 +1976,6 @@
*/
mb();
- clk_disable(msm_uport->clk); /* to balance local clk_enable() */
if (msm_uport->clk_state != MSM_HS_CLK_OFF) {
clk_disable(msm_uport->clk); /* to balance clk_state */
if (msm_uport->pclk)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 35327cc..ff4bbad 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -858,6 +858,32 @@
*idx = (*idx + 1) & (DBG_DATA_MAX-1);
}
+
+static unsigned int ep_addr_txdbg_mask;
+module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
+static unsigned int ep_addr_rxdbg_mask;
+module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
+
+static int allow_dbg_print(u8 addr)
+{
+ int dir, num;
+
+ /* allow bus wide events */
+ if (addr == 0xff)
+ return 1;
+
+ dir = addr & USB_ENDPOINT_DIR_MASK ? TX : RX;
+ num = addr & ~USB_ENDPOINT_DIR_MASK;
+ num = 1 << num;
+
+ if ((dir == TX) && (num & ep_addr_txdbg_mask))
+ return 1;
+ if ((dir == RX) && (num & ep_addr_rxdbg_mask))
+ return 1;
+
+ return 0;
+}
+
/**
* dbg_print: prints the common part of the event
* @addr: endpoint address
@@ -871,6 +897,9 @@
unsigned int stamp;
unsigned long flags;
+ if (!allow_dbg_print(addr))
+ return;
+
write_lock_irqsave(&dbg_data.lck, flags);
do_gettimeofday(&tval);
@@ -1407,7 +1436,7 @@
n = hw_ep_bit(mEp->num, mEp->dir);
pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
- "dTD_update_fail_count: %lu"
+ "dTD_update_fail_count: %lu "
"mEp->dTD_update_fail_count: %lu\n", __func__,
hw_cread(CAP_ENDPTPRIME, ~0),
hw_cread(CAP_ENDPTSTAT, ~0),
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 69a36af..380ef87 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -755,6 +755,8 @@
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
+ if (!f->hs_descriptors)
+ goto fail;
acm->hs.in = usb_find_endpoint(acm_hs_function,
f->hs_descriptors, &acm_hs_in_desc);
@@ -772,6 +774,11 @@
return 0;
fail:
+ if (f->hs_descriptors)
+ usb_free_descriptors(f->hs_descriptors);
+ if (f->descriptors)
+ usb_free_descriptors(f->descriptors);
+
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 66cdcb1..aab5b98 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
+#include <linux/debugfs.h>
#include <mach/diag_bridge.h>
#define DRIVER_DESC "USB host diag bridge driver"
@@ -35,6 +36,12 @@
struct kref kref;
struct diag_bridge_ops *ops;
struct platform_device *pdev;
+
+ /* debugging counters */
+ unsigned long bytes_to_host;
+ unsigned long bytes_to_mdm;
+ unsigned pending_reads;
+ unsigned pending_writes;
};
struct diag_bridge *__dev;
@@ -84,6 +91,9 @@
urb->transfer_buffer,
urb->transfer_buffer_length,
urb->status < 0 ? urb->status : urb->actual_length);
+
+ dev->bytes_to_host += urb->actual_length;
+ dev->pending_reads--;
}
int diag_bridge_read(char *data, int size)
@@ -119,10 +129,12 @@
usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
diag_bridge_read_cb, dev);
usb_anchor_urb(urb, &dev->submitted);
+ dev->pending_reads++;
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+ dev->pending_reads--;
usb_unanchor_urb(urb);
usb_free_urb(urb);
return ret;
@@ -151,6 +163,9 @@
urb->transfer_buffer,
urb->transfer_buffer_length,
urb->status < 0 ? urb->status : urb->actual_length);
+
+ dev->bytes_to_mdm += urb->actual_length;
+ dev->pending_writes--;
}
int diag_bridge_write(char *data, int size)
@@ -186,10 +201,12 @@
usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
diag_bridge_write_cb, dev);
usb_anchor_urb(urb, &dev->submitted);
+ dev->pending_writes++;
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
- err("submitting urb failed err:%d", ret);
+ dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+ dev->pending_writes--;
usb_unanchor_urb(urb);
usb_free_urb(urb);
return ret;
@@ -211,6 +228,79 @@
kfree(dev);
}
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE 512
+static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct diag_bridge *dev = __dev;
+ char *buf;
+ int ret;
+
+ buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = scnprintf(buf, DEBUG_BUF_SIZE,
+ "epin:%d, epout:%d\n"
+ "bytes to host: %lu\n"
+ "bytes to mdm: %lu\n"
+ "pending reads: %u\n"
+ "pending writes: %u\n"
+ "last error: %d\n",
+ dev->in_epAddr, dev->out_epAddr,
+ dev->bytes_to_host, dev->bytes_to_mdm,
+ dev->pending_reads, dev->pending_writes,
+ dev->err);
+
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t diag_reset_stats(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct diag_bridge *dev = __dev;
+
+ dev->bytes_to_host = dev->bytes_to_mdm = 0;
+ dev->pending_reads = dev->pending_writes = 0;
+
+ return count;
+}
+
+const struct file_operations diag_stats_ops = {
+ .read = diag_read_stats,
+ .write = diag_reset_stats,
+};
+
+static struct dentry *dent;
+
+static void diag_bridge_debugfs_init(void)
+{
+ struct dentry *dfile;
+
+ dent = debugfs_create_dir("diag_bridge", 0);
+ if (IS_ERR(dent))
+ return;
+
+ dfile = debugfs_create_file("status", 0444, dent, 0, &diag_stats_ops);
+ if (!dfile || IS_ERR(dfile))
+ debugfs_remove(dent);
+}
+
+static void diag_bridge_debugfs_cleanup(void)
+{
+ if (dent) {
+ debugfs_remove_recursive(dent);
+ dent = NULL;
+ }
+}
+#else
+static inline void diag_bridge_debugfs_init(void) { }
+static inline void diag_bridge_debugfs_cleanup(void) { }
+#endif
+
static int
diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
{
@@ -265,7 +355,7 @@
}
usb_set_intfdata(ifc, dev);
-
+ diag_bridge_debugfs_init();
platform_device_add(dev->pdev);
dev_dbg(&dev->udev->dev, "%s: complete\n", __func__);
@@ -286,6 +376,7 @@
dev_dbg(&dev->udev->dev, "%s:\n", __func__);
platform_device_del(dev->pdev);
+ diag_bridge_debugfs_cleanup();
kref_put(&dev->kref, diag_bridge_delete);
usb_set_intfdata(ifc, NULL);
}
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 00e4fda..4e1895f 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -37,11 +37,13 @@
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
+#include <linux/mfd/pm8xxx/misc.h>
#include <linux/pm_qos_params.h>
#include <linux/power_supply.h>
#include <mach/clk.h>
#include <mach/msm_xo.h>
+#include <mach/msm_bus.h>
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -570,6 +572,9 @@
writel_relaxed(val, USB_OTGSC);
ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
+ } else if (pdata->otg_control == OTG_PMIC_CONTROL) {
+ /* Enable PMIC pull-up */
+ pm8xxx_usb_id_pullup(1);
}
return 0;
@@ -607,7 +612,7 @@
struct usb_bus *bus = otg->host;
struct msm_otg_platform_data *pdata = motg->pdata;
int cnt = 0;
- bool host_bus_suspend;
+ bool host_bus_suspend, dcp;
u32 phy_ctrl_val = 0, cmd_val;
u32 portsc;
@@ -616,6 +621,7 @@
disable_irq(motg->irq);
host_bus_suspend = otg->host && !test_bit(ID, &motg->inputs);
+ dcp = motg->chg_type == USB_DCP_CHARGER;
/*
* Chipidea 45-nm PHY suspend sequence:
*
@@ -688,7 +694,11 @@
cmd_val |= ULPI_STP_CTRL;
writel_relaxed(cmd_val, USB_USBCMD);
- if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend) {
+ /*
+ * BC1.2 spec mandates PD to enable VDP_SRC when charging from DCP.
+ * PHY retention and collapse can not happen with VDP_SRC enabled.
+ */
+ if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend && !dcp) {
phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
if (motg->pdata->otg_control == OTG_PHY_CONTROL)
/* Enable PHY HV interrupts to wake MPM/Link */
@@ -707,7 +717,8 @@
/* usb phy no more require TCXO clock, hence vote for TCXO disable */
clk_disable_unprepare(motg->xo_handle);
- if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !host_bus_suspend) {
+ if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
+ !host_bus_suspend && !dcp) {
msm_hsusb_ldo_enable(motg, 0);
motg->lpm_flags |= PHY_PWR_COLLAPSED;
}
@@ -1122,6 +1133,7 @@
static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
{
+ int ret;
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
struct msm_otg_platform_data *pdata = motg->pdata;
@@ -1142,11 +1154,27 @@
* power collapse(pc) while running in peripheral mode.
*/
otg_pm_qos_update_latency(motg, 1);
+ /* Configure BUS performance parameters for MAX bandwidth */
+ if (motg->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ motg->bus_perf_client, 1);
+ if (ret)
+ dev_err(motg->otg.dev, "%s: Failed to vote for "
+ "bus bandwidth %d\n", __func__, ret);
+ }
usb_gadget_vbus_connect(otg->gadget);
} else {
dev_dbg(otg->dev, "gadget off\n");
usb_gadget_vbus_disconnect(otg->gadget);
otg_pm_qos_update_latency(motg, 0);
+ /* Configure BUS performance parameters to default */
+ if (motg->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ motg->bus_perf_client, 0);
+ if (ret)
+ dev_err(motg->otg.dev, "%s: Failed to devote "
+ "for bus bw %d\n", __func__, ret);
+ }
if (pdata->setup_gpio)
pdata->setup_gpio(OTG_STATE_UNDEFINED);
}
@@ -1283,6 +1311,8 @@
ulpi_write(otg, 0x01, 0x0C);
ulpi_write(otg, 0x10, 0x0F);
ulpi_write(otg, 0x10, 0x12);
+ /* Disable PMIC ID pull-up */
+ pm8xxx_usb_id_pullup(0);
/* Enable ACA ID detection */
ulpi_write(otg, 0x20, 0x85);
aca_id_turned_on = true;
@@ -1415,6 +1445,9 @@
ulpi_write(otg, chg_det, 0x34);
break;
case SNPS_28NM_INTEGRATED_PHY:
+ /* Turn off VDP_SRC */
+ ulpi_write(otg, 0x3, 0x86);
+ msleep(20);
/*
* Configure DM as current source, DP as current sink
* and enable battery charging comparators.
@@ -1616,8 +1649,8 @@
#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
-#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
-#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+#define MSM_CHG_PRIMARY_DET_TIME (50 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (50 * HZ/1000) /* TVDMSRC_ON */
static void msm_chg_detect_work(struct work_struct *w)
{
struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
@@ -1834,6 +1867,8 @@
case USB_CHG_STATE_DETECTED:
switch (motg->chg_type) {
case USB_DCP_CHARGER:
+ /* Enable VDP_SRC */
+ ulpi_write(otg, 0x2, 0x85);
msm_otg_notify_charger(motg,
IDEV_CHG_MAX);
pm_runtime_put_noidle(otg->dev);
@@ -2601,6 +2636,14 @@
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ if (motg->pdata->bus_scale_table) {
+ motg->bus_perf_client =
+ msm_bus_scale_register_client(motg->pdata->bus_scale_table);
+ if (!motg->bus_perf_client)
+ dev_err(motg->otg.dev, "%s: Failed to register BUS "
+ "scaling client!!\n", __func__);
+ }
+
return 0;
remove_otg:
@@ -2702,6 +2745,9 @@
if (motg->pdata->swfi_latency)
pm_qos_remove_request(&motg->pm_qos_req_dma);
+ if (motg->bus_perf_client)
+ msm_bus_scale_unregister_client(motg->bus_perf_client);
+
kfree(motg);
return 0;
}
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index f261931..d3f8b2b 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -174,6 +174,10 @@
select FB_MSM_MIPI_DSI
default n
+config FB_MSM_MIPI_DSI_NT35510
+ bool
+ select FB_MSM_MIPI_DSI
+
config FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
bool
select FB_MSM_MIPI_DSI
@@ -286,6 +290,16 @@
select FB_MSM_MIPI_DSI_RENESAS
default n
+config FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+ bool
+ select FB_MSM_MIPI_DSI_NT35510
+ default n
+
+config FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+ bool
+ select FB_MSM_MIPI_DSI_NT35510
+ default n
+
config FB_MSM_MIPI_CHIMEI_WXGA
bool "LVDS Chimei WXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
@@ -295,6 +309,15 @@
The panel is connected to the host
via Toshiba DSI-to-LVDS bridge.
+config FB_MSM_MIPI_CHIMEI_WUXGA
+ bool "LVDS Chimei WUXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
+ select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
+ ---help---
+ Support for Chimei WUXGA (1920x1200) panel.
+ The panel is using a serial LVDS input.
+ The panel is connected to the host
+ via Toshiba DSI-to-LVDS bridge.
+
config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
bool
select FB_MSM_MIPI_DSI_TRULY
@@ -428,8 +451,11 @@
select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+ select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
select FB_MSM_MIPI_SIMULATOR_VIDEO
select FB_MSM_MIPI_CHIMEI_WXGA
+ select FB_MSM_MIPI_CHIMEI_WUXGA
---help---
Support for MIPI panel auto detect
@@ -463,10 +489,20 @@
select FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT
select FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT
select FB_MSM_MIPI_NOVATEK_CMD_QHD_PT
+ select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+ select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
select FB_MSM_MIPI_SIMULATOR_VIDEO
---help---
Support for LCDC + MIPI panel auto detect
+config FB_MSM_LVDS_MIPI_PANEL_DETECT
+ bool "LVDS + MIPI Panel Auto Detect"
+ select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
+ select FB_MSM_LVDS_CHIMEI_WXGA
+ select FB_MSM_MIPI_CHIMEI_WXGA
+ ---help---
+ Support for LVDS + MIPI panel auto detect
+
config FB_MSM_MDDI_PRISM_WVGA
bool "MDDI Prism WVGA Panel"
select FB_MSM_MDDI
@@ -525,10 +561,22 @@
bool "MIPI Chimei WXGA PT Panel"
select FB_MSM_MIPI_CHIMEI_WXGA
+config FB_MSM_MIPI_CHIMEI_WUXGA_PANEL
+ bool "MIPI Chimei WUXGA Panel"
+ select FB_MSM_MIPI_CHIMEI_WUXGA
+
config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT_PANEL
bool "MIPI Truly Video WVGA PT Panel"
select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
+config FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT_PANEL
+ bool "MIPI NT35510 Video WVGA PT Panel"
+ select FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT
+
+config FB_MSM_MIPI_NT35510_CMD_WVGA_PT_PANEL
+ bool "MIPI NT35510 Command WVGA PT Panel"
+ select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
+
config FB_MSM_MIPI_SIMULATOR_VIDEO_PANEL
bool "MIPI Simulator Video Panel"
select FB_MSM_MIPI_SIMULATOR_VIDEO
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index 2d40b15..bd7628d 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -76,6 +76,7 @@
obj-$(CONFIG_FB_MSM_MIPI_DSI_NOVATEK) += mipi_novatek.o
obj-$(CONFIG_FB_MSM_MIPI_DSI_RENESAS) += mipi_renesas.o
obj-$(CONFIG_FB_MSM_MIPI_DSI_TRULY) += mipi_truly.o
+obj-$(CONFIG_FB_MSM_MIPI_DSI_NT35510) += mipi_NT35510.o
obj-$(CONFIG_FB_MSM_MIPI_DSI_SIMULATOR) += mipi_simulator.o
# MIPI Bridge
@@ -116,7 +117,9 @@
obj-y += mipi_toshiba_video_wvga_pt.o mipi_toshiba_video_wsvga_pt.o
obj-y += mipi_novatek_video_qhd_pt.o mipi_novatek_cmd_qhd_pt.o
obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
+obj-y += mipi_NT35510_video_wvga_pt.o mipi_NT35510_cmd_wvga_pt.o
obj-y += mipi_chimei_wxga_pt.o
+obj-y += mipi_chimei_wuxga.o
obj-y += mipi_truly_video_wvga_pt.o
else
obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT) += mipi_toshiba_video_wvga_pt.o
@@ -125,9 +128,13 @@
obj-$(CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT) += mipi_novatek_cmd_qhd_pt.o
obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
obj-$(CONFIG_FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT) += mipi_renesas_cmd_fwvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT) += mipi_renesas_video_fwvga_pt.o
obj-$(CONFIG_FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT) += mipi_truly_video_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NT35510_CMD_WVGA_PT) += mipi_NT35510_cmd_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT) += mipi_NT35510_video_wvga_pt.o
obj-$(CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO) += mipi_simulator_video.o
obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WXGA) += mipi_chimei_wxga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WUXGA) += mipi_chimei_wuxga.o
endif
obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 7fd4c56..07a075c 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1000,14 +1000,15 @@
return;
external_common_state->speaker_allocation_block = sad[1];
- DEV_DBG("EDID: speaker allocation data=%s%s%s%s%s%s%s\n",
+ DEV_DBG("EDID: speaker allocation data SP byte = %08x %s%s%s%s%s%s%s\n",
+ sad[1],
(sad[1] & BIT(0)) ? "FL/FR," : "",
(sad[1] & BIT(1)) ? "LFE," : "",
(sad[1] & BIT(2)) ? "FC," : "",
(sad[1] & BIT(3)) ? "RL/RR," : "",
(sad[1] & BIT(4)) ? "RC," : "",
(sad[1] & BIT(5)) ? "FLC/FRC," : "",
- (sad[1] & BIT(6)) ? "LFE," : "");
+ (sad[1] & BIT(6)) ? "RLC/RRC," : "");
}
static void hdmi_edid_extract_audio_data_blocks(const uint8 *in_buf)
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 56a6483..93e6d40 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -64,6 +64,8 @@
EXPORT_SYMBOL(hdmi_msm_state_mutex);
static DEFINE_MUTEX(hdcp_auth_state_mutex);
+static void hdmi_msm_dump_regs(const char *prefix);
+
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdmi_msm_hdcp_enable(void);
#else
@@ -3280,14 +3282,23 @@
}
EXPORT_SYMBOL(hdmi_audio_packet_enable);
-static void hdmi_msm_audio_info_setup(boolean enabled, int num_of_channels,
- int level_shift, boolean down_mix)
+
+/* TO-DO: return -EINVAL when num_of_channels and channel_allocation
+ * does not match CEA 861-D spec.
+*/
+int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
+ u32 channel_allocation, u32 level_shift, bool down_mix)
{
- uint32 channel_allocation = 0; /* Default to FR,FL */
uint32 channel_count = 1; /* Default to 2 channels
-> See Table 17 in CEA-D spec */
uint32 check_sum, audio_info_0_reg, audio_info_1_reg;
uint32 audio_info_ctrl_reg;
+ u32 aud_pck_ctrl_2_reg;
+ u32 layout;
+
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+ aud_pck_ctrl_2_reg = 1 | (layout << 1);
+ HDMI_OUTP(0x00044, aud_pck_ctrl_2_reg);
/* Please see table 20 Audio InfoFrame in HDMI spec
FL = front left
@@ -3310,6 +3321,7 @@
if (enabled) {
switch (num_of_channels) {
case MSM_HDMI_AUDIO_CHANNEL_2:
+ channel_allocation = 0; /* Default to FR,FL */
break;
case MSM_HDMI_AUDIO_CHANNEL_4:
channel_count = 3;
@@ -3327,6 +3339,9 @@
channel_allocation = 0x1f;
break;
default:
+ pr_err("%s(): Unsupported num_of_channels = %u\n",
+ __func__, num_of_channels);
+ return -EINVAL;
break;
}
@@ -3382,7 +3397,14 @@
}
/* HDMI_INFOFRAME_CTRL0[0x002C] */
HDMI_OUTP(0x002C, audio_info_ctrl_reg);
+
+
+ hdmi_msm_dump_regs("HDMI-AUDIO-ON: ");
+
+ return 0;
+
}
+EXPORT_SYMBOL(hdmi_msm_audio_info_setup);
static void hdmi_msm_en_gc_packet(boolean av_mute_is_requested)
{
@@ -3488,7 +3510,7 @@
hdmi_msm_audio_acr_setup(TRUE,
external_common_state->video_resolution,
msm_hdmi_sample_rate, channels);
- hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
+ hdmi_msm_audio_info_setup(TRUE, channels, 0, 0, FALSE);
/* Turn on Audio FIFO and SAM DROP ISR */
HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) | BIT(1) | BIT(3));
@@ -3519,7 +3541,7 @@
return -ETIMEDOUT;
}
}
- hdmi_msm_audio_info_setup(FALSE, 0, 0, FALSE);
+ hdmi_msm_audio_info_setup(FALSE, 0, 0, 0, FALSE);
hdmi_msm_audio_acr_setup(FALSE, 0, 0, 0);
DEV_INFO("HDMI Audio: Disabled\n");
return 0;
@@ -4042,7 +4064,7 @@
return rc;
}
}
- hdmi_msm_audio_info_setup(TRUE, 0, 0, FALSE);
+ hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
mutex_lock(&external_common_state_hpd_mutex);
hdmi_msm_state->panel_power_on = TRUE;
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index 7ef437c..a69c64f 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -19,9 +19,10 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
-#include <mach/hardware.h>
#include <linux/io.h>
-
+#include <mach/hardware.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <linux/semaphore.h>
@@ -29,10 +30,9 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <mach/clk.h>
#include "msm_fb.h"
-
+#include "mdp4.h"
static int lvds_probe(struct platform_device *pdev);
static int lvds_remove(struct platform_device *pdev);
@@ -57,6 +57,126 @@
static struct lcdc_platform_data *lvds_pdata;
+static void lvds_init(struct msm_fb_data_type *mfd)
+{
+ unsigned int lvds_intf, lvds_phy_cfg0;
+
+ MDP_OUTP(MDP_BASE + 0xc2034, 0x33);
+ usleep(1000);
+
+ /* LVDS PHY PLL configuration */
+ MDP_OUTP(MDP_BASE + 0xc3000, 0x08);
+ MDP_OUTP(MDP_BASE + 0xc3004, 0x87);
+ MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
+ MDP_OUTP(MDP_BASE + 0xc300c, 0x06);
+ MDP_OUTP(MDP_BASE + 0xc3014, 0x20);
+ MDP_OUTP(MDP_BASE + 0xc3018, 0x0F);
+ MDP_OUTP(MDP_BASE + 0xc301c, 0x01);
+ MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
+ MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+ MDP_OUTP(MDP_BASE + 0xc3028, 0x07);
+ MDP_OUTP(MDP_BASE + 0xc302c, 0x00);
+ MDP_OUTP(MDP_BASE + 0xc3030, 0x1c);
+ MDP_OUTP(MDP_BASE + 0xc3034, 0x01);
+ MDP_OUTP(MDP_BASE + 0xc3038, 0x00);
+ MDP_OUTP(MDP_BASE + 0xc3040, 0xC0);
+ MDP_OUTP(MDP_BASE + 0xc3044, 0x00);
+ MDP_OUTP(MDP_BASE + 0xc3048, 0x30);
+ MDP_OUTP(MDP_BASE + 0xc304c, 0x00);
+
+ MDP_OUTP(MDP_BASE + 0xc3000, 0x11);
+ MDP_OUTP(MDP_BASE + 0xc3064, 0x05);
+ MDP_OUTP(MDP_BASE + 0xc3050, 0x20);
+
+ MDP_OUTP(MDP_BASE + 0xc3000, 0x01);
+ /* Wait until LVDS PLL is locked and ready */
+ while (!readl_relaxed(MDP_BASE + 0xc3080))
+ cpu_relax();
+
+ writel_relaxed(0x00, mmss_cc_base + 0x0264);
+ writel_relaxed(0x00, mmss_cc_base + 0x0094);
+
+ writel_relaxed(0x02, mmss_cc_base + 0x00E4);
+
+ writel_relaxed((0x80 | readl_relaxed(mmss_cc_base + 0x00E4)),
+ mmss_cc_base + 0x00E4);
+ usleep(1000);
+ writel_relaxed((~0x80 & readl_relaxed(mmss_cc_base + 0x00E4)),
+ mmss_cc_base + 0x00E4);
+
+ writel_relaxed(0x05, mmss_cc_base + 0x0094);
+ writel_relaxed(0x02, mmss_cc_base + 0x0264);
+ /* Wait until LVDS pixel clock output is enabled */
+ mb();
+
+ if (mfd->panel_info.bpp == 24) {
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2014, 0x03040508);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2018, 0x00000102);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc201c, 0x0c0d1011);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2020, 0x00090a0b);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2024, 0x151a191a);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2028, 0x00121314);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc202c, 0x1706071b);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2030, 0x000e0f16);
+
+ if (mfd->panel_info.lvds.channel_mode ==
+ LVDS_DUAL_CHANNEL_MODE) {
+ lvds_intf = 0x0001ff80;
+ lvds_phy_cfg0 = BIT(6) | BIT(7);
+ if (mfd->panel_info.lvds.channel_swap)
+ lvds_intf |= BIT(4);
+ } else {
+ lvds_intf = 0x00010f84;
+ lvds_phy_cfg0 = BIT(6);
+ }
+ } else if (mfd->panel_info.bpp == 18) {
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2014, 0x03040508);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2018, 0x00000102);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc201c, 0x0c0d1011);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2020, 0x00090a0b);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2024, 0x1518191a);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2028, 0x00121314);
+
+ if (mfd->panel_info.lvds.channel_mode ==
+ LVDS_DUAL_CHANNEL_MODE) {
+ lvds_intf = 0x00017788;
+ lvds_phy_cfg0 = BIT(6) | BIT(7);
+ if (mfd->panel_info.lvds.channel_swap)
+ lvds_intf |= BIT(4);
+ } else {
+ lvds_intf = 0x0001078c;
+ lvds_phy_cfg0 = BIT(6);
+ }
+ }
+
+ /* MDP_LVDSPHY_CFG0 */
+ MDP_OUTP(MDP_BASE + 0xc3100, lvds_phy_cfg0);
+ /* MDP_LCDC_LVDS_INTF_CTL */
+ MDP_OUTP(MDP_BASE + 0xc2000, lvds_intf);
+ MDP_OUTP(MDP_BASE + 0xc3108, 0x30);
+ lvds_phy_cfg0 |= BIT(4);
+
+ /* Wait until LVDS PHY registers are configured */
+ mb();
+ usleep(1);
+ /* MDP_LVDSPHY_CFG0, enable serialization */
+ MDP_OUTP(MDP_BASE + 0xc3100, lvds_phy_cfg0);
+}
+
static int lvds_off(struct platform_device *pdev)
{
int ret = 0;
@@ -65,7 +185,8 @@
mfd = platform_get_drvdata(pdev);
ret = panel_next_off(pdev);
- clk_disable(lvds_clk);
+ if (lvds_clk)
+ clk_disable(lvds_clk);
if (lvds_pdata && lvds_pdata->lcdc_power_save)
lvds_pdata->lcdc_power_save(0);
@@ -97,22 +218,24 @@
#endif
mfd = platform_get_drvdata(pdev);
- mfd->fbi->var.pixclock = clk_round_rate(lvds_clk,
- mfd->fbi->var.pixclock);
- ret = clk_set_rate(lvds_clk, mfd->fbi->var.pixclock);
- if (ret) {
- pr_err("%s: Can't set lvds clock to rate %u\n",
- __func__, mfd->fbi->var.pixclock);
- goto out;
+ if (lvds_clk) {
+ mfd->fbi->var.pixclock = clk_round_rate(lvds_clk,
+ mfd->fbi->var.pixclock);
+ ret = clk_set_rate(lvds_clk, mfd->fbi->var.pixclock);
+ if (ret) {
+ pr_err("%s: Can't set lvds clock to rate %u\n",
+ __func__, mfd->fbi->var.pixclock);
+ goto out;
+ }
+ clk_enable(lvds_clk);
}
- clk_enable(lvds_clk);
-
if (lvds_pdata && lvds_pdata->lcdc_power_save)
lvds_pdata->lcdc_power_save(1);
if (lvds_pdata && lvds_pdata->lcdc_gpio_config)
ret = lvds_pdata->lcdc_gpio_config(1);
+ lvds_init(mfd);
ret = panel_next_on(pdev);
out:
@@ -182,8 +305,11 @@
mfd->fb_imgType = MDP_RGB_565;
fbi = mfd->fbi;
- fbi->var.pixclock = clk_round_rate(lvds_clk,
- mfd->panel_info.clk_rate);
+ if (lvds_clk) {
+ fbi->var.pixclock = clk_round_rate(lvds_clk,
+ mfd->panel_info.clk_rate);
+ }
+
fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
@@ -224,9 +350,9 @@
static int __init lvds_driver_init(void)
{
lvds_clk = clk_get(NULL, "lvds_clk");
- if (IS_ERR(lvds_clk)) {
+ if (IS_ERR_OR_NULL(lvds_clk)) {
pr_err("Couldnt find lvds_clk\n");
- return -EINVAL;
+ lvds_clk = NULL;
}
return lvds_register_driver();
diff --git a/drivers/video/msm/lvds_chimei_wxga.c b/drivers/video/msm/lvds_chimei_wxga.c
index 2c6b6d4..9a385b9 100644
--- a/drivers/video/msm/lvds_chimei_wxga.c
+++ b/drivers/video/msm/lvds_chimei_wxga.c
@@ -11,9 +11,19 @@
*/
#include "msm_fb.h"
+#include <linux/pwm.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
-static struct msm_panel_common_pdata *cm_pdata;
+#define LVDS_CHIMEI_PWM_FREQ_HZ 300
+#define LVDS_CHIMEI_PWM_PERIOD_USEC (USEC_PER_SEC / LVDS_CHIMEI_PWM_FREQ_HZ)
+#define LVDS_CHIMEI_PWM_LEVEL 255
+#define LVDS_CHIMEI_PWM_DUTY_LEVEL \
+ (LVDS_CHIMEI_PWM_PERIOD_USEC / LVDS_CHIMEI_PWM_LEVEL)
+
+
+static struct lvds_panel_platform_data *cm_pdata;
static struct platform_device *cm_fbpdev;
+static struct pwm_device *bl_lpm;
static int lvds_chimei_panel_on(struct platform_device *pdev)
{
@@ -27,6 +37,26 @@
static void lvds_chimei_set_backlight(struct msm_fb_data_type *mfd)
{
+ int ret;
+
+ pr_debug("%s: back light level %d\n", __func__, mfd->bl_level);
+
+ if (bl_lpm) {
+ ret = pwm_config(bl_lpm, LVDS_CHIMEI_PWM_DUTY_LEVEL *
+ mfd->bl_level, LVDS_CHIMEI_PWM_PERIOD_USEC);
+ if (ret) {
+ pr_err("pwm_config on lpm failed %d\n", ret);
+ return;
+ }
+ if (mfd->bl_level) {
+ ret = pwm_enable(bl_lpm);
+ if (ret)
+ pr_err("pwm enable/disable on lpm failed"
+ "for bl %d\n", mfd->bl_level);
+ } else {
+ pwm_disable(bl_lpm);
+ }
+ }
}
static int __devinit lvds_chimei_probe(struct platform_device *pdev)
@@ -40,6 +70,17 @@
return 0;
}
+ if (cm_pdata != NULL)
+ bl_lpm = pwm_request(cm_pdata->gpio[0],
+ "backlight");
+
+ if (bl_lpm == NULL || IS_ERR(bl_lpm)) {
+ pr_err("%s pwm_request() failed\n", __func__);
+ bl_lpm = NULL;
+ }
+ pr_debug("bl_lpm = %p lpm = %d\n", bl_lpm,
+ cm_pdata->gpio[0]);
+
cm_fbpdev = msm_fb_add_device(pdev);
if (!cm_fbpdev) {
dev_err(&pdev->dev, "failed to add msm_fb device\n");
@@ -85,8 +126,8 @@
return ret;
pinfo = &lvds_chimei_panel_data.panel_info;
- pinfo->xres = 320;
- pinfo->yres = 240;
+ pinfo->xres = 1366;
+ pinfo->yres = 768;
MSM_FB_SINGLE_MODE_PANEL(pinfo);
pinfo->type = LVDS_PANEL;
pinfo->pdest = DISPLAY_1;
@@ -94,7 +135,7 @@
pinfo->bpp = 24;
pinfo->fb_num = 2;
pinfo->clk_rate = 75000000;
- pinfo->bl_max = 15;
+ pinfo->bl_max = 255;
pinfo->bl_min = 1;
/*
@@ -107,12 +148,14 @@
pinfo->lcdc.v_back_porch = 0;
pinfo->lcdc.v_front_porch = 38;
pinfo->lcdc.v_pulse_width = 20;
- pinfo->lcdc.border_clr = 0xffff00;
pinfo->lcdc.underflow_clr = 0xff;
pinfo->lcdc.hsync_skew = 0;
pinfo->lvds.channel_mode = LVDS_SINGLE_CHANNEL_MODE;
- pinfo->lcdc.xres_pad = 1046;
- pinfo->lcdc.yres_pad = 528;
+
+ /* Set border color, padding only for reducing active display region */
+ pinfo->lcdc.border_clr = 0x0;
+ pinfo->lcdc.xres_pad = 0;
+ pinfo->lcdc.yres_pad = 0;
ret = platform_device_register(&this_device);
if (ret)
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 512480c..43520e0 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -468,11 +468,16 @@
int mdp_ppp_pipe_wait(void)
{
int ret = 1;
+ boolean wait;
+ unsigned long flag;
/* wait 5 seconds for the operation to complete before declaring
the MDP hung */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ wait = mdp_ppp_waiting;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
- if (mdp_ppp_waiting == TRUE) {
+ if (wait == TRUE) {
ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
5 * HZ);
@@ -548,6 +553,7 @@
void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
{
+ unsigned long flag;
/* complete all the writes before starting */
wmb();
@@ -561,7 +567,9 @@
mdp_enable_irq(term);
INIT_COMPLETION(mdp_ppp_comp);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_ppp_waiting = TRUE;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
outpdw(MDP_BASE + 0x30, 0x1000);
wait_for_completion_killable(&mdp_ppp_comp);
mdp_disable_irq(term);
@@ -812,128 +820,137 @@
{
uint32 mdp_interrupt = 0;
struct mdp_dma_data *dma;
+ unsigned long flag;
+ /* Ensure all the register write are complete */
+ mb();
mdp_is_in_isr = TRUE;
- do {
- mdp_interrupt = inp32(MDP_INTR_STATUS);
- outp32(MDP_INTR_CLEAR, mdp_interrupt);
- mdp_interrupt &= mdp_intr_mask;
+ mdp_interrupt = inp32(MDP_INTR_STATUS);
+ outp32(MDP_INTR_CLEAR, mdp_interrupt);
- if (mdp_interrupt & TV_ENC_UNDERRUN) {
- mdp_interrupt &= ~(TV_ENC_UNDERRUN);
- mdp_tv_underflow_cnt++;
- }
+ mdp_interrupt &= mdp_intr_mask;
- if (!mdp_interrupt)
- break;
+ if (mdp_interrupt & TV_ENC_UNDERRUN) {
+ mdp_interrupt &= ~(TV_ENC_UNDERRUN);
+ mdp_tv_underflow_cnt++;
+ }
- /* DMA3 TV-Out Start */
- if (mdp_interrupt & TV_OUT_DMA3_START) {
- /* let's disable TV out interrupt */
- mdp_intr_mask &= ~TV_OUT_DMA3_START;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ if (!mdp_interrupt)
+ goto out;
- dma = &dma3_data;
- if (dma->waiting) {
- dma->waiting = FALSE;
- complete(&dma->comp);
- }
- }
-#ifndef CONFIG_FB_MSM_MDP22
- if (mdp_interrupt & MDP_HIST_DONE) {
- outp32(MDP_BASE + 0x94018, 0x3);
- outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
- complete(&mdp_hist_comp);
- }
+ /* DMA3 TV-Out Start */
+ if (mdp_interrupt & TV_OUT_DMA3_START) {
+ /* let's disable TV out interrupt */
+ mdp_intr_mask &= ~TV_OUT_DMA3_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
- /* LCDC UnderFlow */
- if (mdp_interrupt & LCDC_UNDERFLOW) {
- mdp_lcdc_underflow_cnt++;
- /*when underflow happens HW resets all the histogram
- registers that were set before so restore them back
- to normal.*/
- MDP_OUTP(MDP_BASE + 0x94010, 1);
- MDP_OUTP(MDP_BASE + 0x9401c, 2);
- if (mdp_is_hist_start == TRUE) {
- MDP_OUTP(MDP_BASE + 0x94004,
- mdp_hist_frame_cnt);
- MDP_OUTP(MDP_BASE + 0x94000, 1);
- }
- }
- /* LCDC Frame Start */
- if (mdp_interrupt & LCDC_FRAME_START) {
- /* let's disable LCDC interrupt */
- mdp_intr_mask &= ~LCDC_FRAME_START;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
- dma = &dma2_data;
- if (dma->waiting) {
- dma->waiting = FALSE;
- complete(&dma->comp);
- }
- }
-
- /* DMA2 LCD-Out Complete */
- if (mdp_interrupt & MDP_DMA_S_DONE) {
- dma = &dma_s_data;
- dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
- TRUE);
+ dma = &dma3_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
complete(&dma->comp);
}
- /* DMA_E LCD-Out Complete */
- if (mdp_interrupt & MDP_DMA_E_DONE) {
- dma = &dma_s_data;
+ }
+#ifndef CONFIG_FB_MSM_MDP22
+ if (mdp_interrupt & MDP_HIST_DONE) {
+ outp32(MDP_BASE + 0x94018, 0x3);
+ outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
+ complete(&mdp_hist_comp);
+ }
+
+ /* LCDC UnderFlow */
+ if (mdp_interrupt & LCDC_UNDERFLOW) {
+ mdp_lcdc_underflow_cnt++;
+ /*when underflow happens HW resets all the histogram
+ registers that were set before so restore them back
+ to normal.*/
+ MDP_OUTP(MDP_BASE + 0x94010, 1);
+ MDP_OUTP(MDP_BASE + 0x9401c, 2);
+ if (mdp_is_hist_start == TRUE) {
+ MDP_OUTP(MDP_BASE + 0x94004,
+ mdp_hist_frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x94000, 1);
+ }
+ }
+
+ /* LCDC Frame Start */
+ if (mdp_interrupt & LCDC_FRAME_START) {
+ /* let's disable LCDC interrupt */
+ mdp_intr_mask &= ~LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ dma = &dma2_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ }
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_S_DONE) {
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+
+ /* DMA_E LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_E_DONE) {
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+
+#endif
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_P_DONE) {
+ struct timeval now;
+
+ mdp_dma2_last_update_time = ktime_sub(ktime_get_real(),
+ mdp_dma2_last_update_time);
+ if (mdp_debug[MDP_DMA2_BLOCK]) {
+ jiffies_to_timeval(jiffies, &now);
+ mdp_dma2_timeval.tv_usec =
+ now.tv_usec - mdp_dma2_timeval.tv_usec;
+ }
+#ifndef CONFIG_FB_MSM_MDP303
+ dma = &dma2_data;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ dma->busy = FALSE;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+#else
+ if (mdp_prim_panel_type == MIPI_CMD_PANEL) {
+ dma = &dma2_data;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF,
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
TRUE);
complete(&dma->comp);
}
-
#endif
+ }
- /* DMA2 LCD-Out Complete */
- if (mdp_interrupt & MDP_DMA_P_DONE) {
- struct timeval now;
-
- mdp_dma2_last_update_time = ktime_sub(ktime_get_real(),
- mdp_dma2_last_update_time);
- if (mdp_debug[MDP_DMA2_BLOCK]) {
- jiffies_to_timeval(jiffies, &now);
- mdp_dma2_timeval.tv_usec =
- now.tv_usec - mdp_dma2_timeval.tv_usec;
- }
-#ifndef CONFIG_FB_MSM_MDP303
- dma = &dma2_data;
- dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
- TRUE);
- complete(&dma->comp);
-#else
- if (mdp_prim_panel_type == MIPI_CMD_PANEL) {
- dma = &dma2_data;
- dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA2_BLOCK,
- MDP_BLOCK_POWER_OFF, TRUE);
- complete(&dma->comp);
- }
-#endif
- }
- /* PPP Complete */
- if (mdp_interrupt & MDP_PPP_DONE) {
+ /* PPP Complete */
+ if (mdp_interrupt & MDP_PPP_DONE) {
#ifdef CONFIG_FB_MSM_MDP31
- MDP_OUTP(MDP_BASE + 0x00100, 0xFFFF);
+ MDP_OUTP(MDP_BASE + 0x00100, 0xFFFF);
#endif
- mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
- if (mdp_ppp_waiting) {
- mdp_ppp_waiting = FALSE;
- complete(&mdp_ppp_comp);
- }
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (mdp_ppp_waiting) {
+ mdp_ppp_waiting = FALSE;
+ complete(&mdp_ppp_comp);
}
- } while (1);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ }
- mdp_is_in_isr = FALSE;
+out:
+mdp_is_in_isr = FALSE;
return IRQ_HANDLED;
}
@@ -1083,12 +1100,12 @@
static int mdp_off(struct platform_device *pdev)
{
int ret = 0;
+
mdp_histogram_ctrl(FALSE);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
ret = panel_next_off(pdev);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
return ret;
}
@@ -1098,9 +1115,12 @@
#ifdef CONFIG_FB_MSM_MDP40
struct msm_fb_data_type *mfd;
+ mdp4_overlay_ctrl_db_reset();
+
+ mfd = platform_get_drvdata(pdev);
+
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
if (is_mdp4_hw_reset()) {
- mfd = platform_get_drvdata(pdev);
mdp_vsync_cfg_regs(mfd, FALSE);
mdp4_hw_init();
outpdw(MDP_BASE + 0x0038, mdp4_display_intf);
@@ -1112,6 +1132,14 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
ret = panel_next_on(pdev);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP40
+ if (mfd->panel.type == MIPI_CMD_PANEL)
+ mdp4_dsi_cmd_overlay_restore();
+ else if (mfd->panel.type == MDDI_PANEL)
+ mdp4_mddi_overlay_restore();
+#endif
+
return ret;
}
@@ -1193,7 +1221,7 @@
return -EINVAL;
}
if (mdp_bus_scale_handle < 1) {
- printk(KERN_ERR "%s invalid bus handle\n", __func__);
+ pr_debug("%s invalid bus handle\n", __func__);
return -EINVAL;
}
return msm_bus_scale_client_update_request(mdp_bus_scale_handle,
@@ -1290,7 +1318,7 @@
if (IS_ERR(mdp_pclk))
mdp_pclk = NULL;
- if (mdp_rev == MDP_REV_42) {
+ if (mdp_rev >= MDP_REV_42) {
mdp_lut_clk = clk_get(NULL, "lut_mdp");
if (IS_ERR(mdp_lut_clk)) {
ret = PTR_ERR(mdp_lut_clk);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 3862823..155bc54 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -26,6 +26,7 @@
extern spinlock_t mdp_spin_lock;
extern struct mdp4_statistic mdp4_stat;
extern uint32 mdp4_extn_disp;
+extern char *mmss_cc_base; /* mutimedia sub system clock control */
#define MDP4_OVERLAYPROC0_BASE 0x10000
#define MDP4_OVERLAYPROC1_BASE 0x18000
@@ -417,6 +418,7 @@
struct mdp4_overlay_pipe *pipe);
int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
+void mdp4_dma_e_done_dtv(void);
#else
static inline void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe)
@@ -438,6 +440,10 @@
{
return 0;
}
+static inline void mdp4_dma_e_done_dtv(void)
+{
+ return;
+}
#endif
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -513,7 +519,6 @@
void mdp4_overlay1_done_atv(void);
void mdp4_primary_vsync_lcdc(void);
void mdp4_external_vsync_dtv(void);
-void mdp4_mddi_overlay_restore(void);
void mdp4_overlay_lcdc_wait4vsync(struct msm_fb_data_type *mfd);
void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
@@ -523,11 +528,16 @@
#ifndef CONFIG_FB_MSM_MIPI_DSI
void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd);
+void mdp4_mddi_overlay_restore(void);
#else
static inline void mdp4_mddi_dma_busy_wait(struct msm_fb_data_type *mfd)
{
/* empty */
}
+static inline void mdp4_mddi_overlay_restore(void)
+{
+ /* empty */
+}
#endif
void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
@@ -629,6 +639,7 @@
void mdp4_dsi_blt_dmap_busy_wait(struct msm_fb_data_type *mfd);
void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_overlay_restore(void);
#else
static inline void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
{
@@ -643,6 +654,10 @@
{
/* empty */
}
+static inline void mdp4_dsi_cmd_overlay_restore(void)
+{
+ /* empty */
+}
#endif /* MIPI_DSI */
void mdp4_dsi_cmd_kickoff_ui(struct msm_fb_data_type *mfd,
@@ -651,7 +666,6 @@
struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_cmd_overlay_kickoff(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
-void mdp4_dsi_cmd_overlay_restore(void);
void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d);
int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req);
@@ -674,6 +688,7 @@
uint32_t mdp4_ss_table_value(int8_t param, int8_t index);
void mdp4_overlay_status_write(enum mdp4_overlay_status type, bool val);
bool mdp4_overlay_status_read(enum mdp4_overlay_status type);
+void mdp4_overlay_ctrl_db_reset(void);
int mdp4_overlay_writeback_on(struct platform_device *pdev);
int mdp4_overlay_writeback_off(struct platform_device *pdev);
@@ -682,7 +697,6 @@
struct mdp4_overlay_pipe *pipe);
void mdp4_writeback_dma_busy_wait(struct msm_fb_data_type *mfd);
void mdp4_overlay1_done_writeback(struct mdp_dma_data *dma);
-void mdp4_dma_e_done_dtv(void);
int mdp4_writeback_start(struct fb_info *info);
int mdp4_writeback_stop(struct fb_info *info);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 8b61024..bf53c73 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -110,6 +110,14 @@
return overlay_status[type];
}
+void mdp4_overlay_ctrl_db_reset(void)
+{
+ int i;
+
+ for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++)
+ ctrl->mixer_cfg[i] = 0;
+}
+
int mdp4_overlay_mixer_play(int mixer_num)
{
if (mixer_num == MDP4_MIXER2)
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 52a402c..3f12827 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -110,6 +110,8 @@
if (mfd->key != MFD_KEY)
return -EINVAL;
+ mdp4_overlay_ctrl_db_reset();
+
fbi = mfd->fbi;
var = &fbi->var;
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 848e6b9..3dece1f 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -45,73 +45,6 @@
static struct mdp4_overlay_pipe *lcdc_pipe;
static struct completion lcdc_comp;
-static void lvds_init(struct msm_fb_data_type *mfd)
-{
- unsigned int lvds_intf, lvds_phy_cfg0;
-
- if (mfd->panel_info.bpp == 24) {
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc2014, 0x03040508);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2018, 0x00000102);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc201c, 0x0c0d1011);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2020, 0x00090a0b);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc2024, 0x1518191a);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2028, 0x00121314);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc202c, 0x0f16171b);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2030, 0x0006070e);
-
- if (mfd->panel_info.lvds.channel_mode ==
- LVDS_DUAL_CHANNEL_MODE) {
- lvds_intf = 0x0001ff80;
- lvds_phy_cfg0 = BIT(6) | BIT(7);
- if (mfd->panel_info.lvds.channel_swap)
- lvds_intf |= BIT(4);
- } else {
- lvds_intf = 0x00010f84;
- lvds_phy_cfg0 = BIT(6);
- }
- } else if (mfd->panel_info.bpp == 18) {
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc2014, 0x03040508);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2018, 0x00000102);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc201c, 0x0c0d1011);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2020, 0x00090a0b);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc2024, 0x1518191a);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2028, 0x00121314);
-
- if (mfd->panel_info.lvds.channel_mode ==
- LVDS_DUAL_CHANNEL_MODE) {
- lvds_intf = 0x00017788;
- lvds_phy_cfg0 = BIT(6) | BIT(7);
- if (mfd->panel_info.lvds.channel_swap)
- lvds_intf |= BIT(4);
- } else {
- lvds_intf = 0x0001078c;
- lvds_phy_cfg0 = BIT(6);
- }
- }
-
- /* MDP_LVDSPHY_CFG0 */
- MDP_OUTP(MDP_BASE + 0xc3100, lvds_phy_cfg0);
- /* MDP_LCDC_LVDS_INTF_CTL */
- MDP_OUTP(MDP_BASE + 0xc2000, lvds_intf);
- lvds_phy_cfg0 |= BIT(4);
- /* MDP_LVDSPHY_CFG0, enable serialization */
- MDP_OUTP(MDP_BASE + 0xc3100, lvds_phy_cfg0);
-}
-
int mdp_lcdc_on(struct platform_device *pdev)
{
int lcdc_width;
@@ -160,6 +93,8 @@
if (mfd->key != MFD_KEY)
return -EINVAL;
+ mdp4_overlay_ctrl_db_reset();
+
fbi = mfd->fbi;
var = &fbi->var;
@@ -303,9 +238,6 @@
#endif
mdp_histogram_ctrl(TRUE);
- if (mfd->panel.type == LVDS_PANEL)
- lvds_init(mfd);
-
ret = panel_next_on(pdev);
if (ret == 0) {
/* enable LCDC block */
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index f9f7954..3997814 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -478,16 +478,20 @@
void mdp_dma2_update(struct msm_fb_data_type *mfd)
#endif
{
+ unsigned long flag;
+
down(&mfd->dma->mutex);
if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
down(&mfd->sem);
mfd->ibuf_flushed = TRUE;
mdp_dma2_update_lcd(mfd);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_enable_irq(MDP_DMA2_TERM);
mfd->dma->busy = TRUE;
INIT_COMPLETION(mfd->dma->comp);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
/* schedule DMA to start */
mdp_dma_schedule(mfd, MDP_DMA2_TERM);
up(&mfd->sem);
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 19dfe82..199e472 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1,7 +1,7 @@
/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
*
* Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 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
@@ -52,6 +52,7 @@
[MDP_RGBX_8888] = 4,
[MDP_Y_CBCR_H2V1] = 1,
[MDP_Y_CBCR_H2V2] = 1,
+ [MDP_Y_CBCR_H2V2_ADRENO] = 1,
[MDP_Y_CRCB_H2V1] = 1,
[MDP_Y_CRCB_H2V2] = 1,
[MDP_YCRYCB_H2V1] = 2,
@@ -535,14 +536,16 @@
#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
(img == MDP_Y_CBCR_H2V2) | \
+ (img == MDP_Y_CBCR_H2V2_ADRENO) | \
(img == MDP_Y_CRCB_H2V1) | \
(img == MDP_Y_CBCR_H2V1))
#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
#define Y_TO_CRCB_RATIO(format) \
- ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\
- (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
+ ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CBCR_H2V2_ADRENO || \
+ format == MDP_Y_CRCB_H2V2) ? 2 : (format == MDP_Y_CBCR_H2V1 || \
+ format == MDP_Y_CRCB_H2V1) ? 1 : 1)
#ifdef CONFIG_ANDROID_PMEM
static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
@@ -589,6 +592,7 @@
uint32 src_width;
uint32 src_height;
uint32 src0_ystride;
+ uint32 src0_y1stride;
uint32 dst_roi_width;
uint32 dst_roi_height;
uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
@@ -868,6 +872,7 @@
break;
case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CBCR_H2V2_ADRENO:
case MDP_Y_CRCB_H2V2:
inpBpp = 1;
src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
@@ -1059,7 +1064,16 @@
}
}
- src0_ystride = src_width * inpBpp;
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+ src0_ystride = ALIGN(src_width, 32) * inpBpp;
+ else
+ src0_ystride = src_width * inpBpp;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+ src0_y1stride = 2 * ALIGN(src_width/2, 32);
+ else
+ src0_y1stride = src0_ystride;
+
dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
/* no need to care about rotation since it's the real-XY. */
@@ -1121,7 +1135,7 @@
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
- (src0_ystride << 16 | src0_ystride));
+ (src0_y1stride << 16 | src0_ystride));
/* setup for rgb 565 */
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
@@ -1362,9 +1376,16 @@
iBuf.mdpImg.imgType = req->src.format;
iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
- iBuf.mdpImg.cbcr_addr =
- (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
- req->src.width * req->src.height);
+
+ if (iBuf.mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
+ iBuf.mdpImg.cbcr_addr =
+ (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+ ALIGN((ALIGN(req->src.width, 32) *
+ ALIGN(req->src.height, 32)), 4096));
+ else
+ iBuf.mdpImg.cbcr_addr =
+ (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+ req->src.width * req->src.height);
iBuf.mdpImg.mdpOp = MDPOP_NOP;
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index 8828a8f..e2a6564 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1625,6 +1625,7 @@
* offsite in vertical axis
*/
case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CBCR_H2V2_ADRENO:
case MDP_Y_CRCB_H2V2:
/* floor( luma_interp_point_left / 2) */
chroma_interp_point_left = luma_interp_point_left >> 1;
@@ -1678,6 +1679,7 @@
break;
case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CBCR_H2V2_ADRENO:
case MDP_Y_CRCB_H2V2:
/*
* cosite in horizontal dir, and offsite in vertical dir
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
new file mode 100644
index 0000000..930b4e9
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -0,0 +1,586 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_common_pdata *mipi_nt35510_pdata;
+static struct dsi_buf nt35510_tx_buf;
+static struct dsi_buf nt35510_rx_buf;
+
+#define NT35510_SLEEP_OFF_DELAY 150
+#define NT35510_DISPLAY_ON_DELAY 150
+
+/* common setting */
+static char exit_sleep[2] = {0x11, 0x00};
+static char display_on[2] = {0x29, 0x00};
+static char display_off[2] = {0x28, 0x00};
+static char enter_sleep[2] = {0x10, 0x00};
+static char write_ram[2] = {0x2c, 0x00}; /* write ram */
+
+static struct dsi_cmd_desc nt35510_display_off_cmds[] = {
+ {DTYPE_DCS_WRITE, 1, 0, 0, 150, sizeof(display_off), display_off},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 150, sizeof(enter_sleep), enter_sleep}
+};
+
+static char cmd0[6] = {
+ 0xF0, 0x55, 0xAA, 0x52,
+ 0x08, 0x01,
+};
+static char cmd1[4] = {
+ 0xBC, 0x00, 0xA0, 0x00,
+};
+static char cmd2[4] = {
+ 0xBD, 0x00, 0xA0, 0x00,
+};
+static char cmd3[3] = {
+ 0xBE, 0x00, 0x79,
+};
+static char cmd4[53] = {
+ 0xD1, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char cmd5[53] = {
+ 0xD2, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char cmd6[53] = {
+ 0xD3, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char cmd7[53] = {
+ 0xD4, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char cmd8[53] = {
+ 0xD5, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char cmd9[53] = {
+ 0xD6, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char cmd10[4] = {
+ 0xB0, 0x0A, 0x0A, 0x0A,
+};
+static char cmd11[4] = {
+ 0xB1, 0x0A, 0x0A, 0x0A,
+};
+static char cmd12[4] = {
+ 0xBA, 0x24, 0x24, 0x24,
+};
+static char cmd13[4] = {
+ 0xB9, 0x24, 0x24, 0x24,
+};
+static char cmd14[4] = {
+ 0xB8, 0x24, 0x24, 0x24,
+};
+static char cmd15[6] = {
+ 0xF0, 0x55, 0xAA, 0x52,
+ 0x08, 0x00,
+};
+static char cmd16[2] = {
+ 0xB3, 0x00,
+};
+static char cmd17[2] = {
+ 0xB4, 0x10,
+};
+static char cmd18[2] = {
+ 0xB6, 0x02,
+};
+static char cmd19[3] = {
+ 0xB1, 0xEC, 0x00,
+};
+static char cmd20[4] = {
+ 0xBC, 0x05, 0x05, 0x05,
+};
+static char cmd21[3] = {
+ 0xB7, 0x20, 0x20,
+};
+static char cmd22[5] = {
+ 0xB8, 0x01, 0x03, 0x03,
+ 0x03,
+};
+static char cmd23[19] = {
+ 0xC8, 0x01, 0x00, 0x78,
+ 0x50, 0x78, 0x50, 0x78,
+ 0x50, 0x78, 0x50, 0xC8,
+ 0x3C, 0x3C, 0xC8, 0xC8,
+ 0x3C, 0x3C, 0xC8,
+};
+static char cmd24[6] = {
+ 0xBD, 0x01, 0x84, 0x07,
+ 0x31, 0x00,
+};
+static char cmd25[6] = {
+ 0xBE, 0x01, 0x84, 0x07,
+ 0x31, 0x00,
+};
+static char cmd26[6] = {
+ 0xBF, 0x01, 0x84, 0x07,
+ 0x31, 0x00,
+};
+static char cmd27[2] = {
+ 0x35, 0x00,
+};
+static char config_MADCTL[2] = {0x36, 0x00};
+static struct dsi_cmd_desc nt35510_cmd_display_on_cmds[] = {
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd0), cmd0},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd1), cmd1},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd2), cmd2},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd3), cmd3},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd4), cmd4},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd5), cmd5},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd6), cmd6},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd7), cmd7},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd8), cmd8},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd9), cmd9},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd10), cmd10},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd11), cmd11},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd12), cmd12},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd13), cmd13},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd14), cmd14},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd15), cmd15},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd16), cmd16},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd17), cmd17},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd18), cmd18},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd19), cmd19},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd20), cmd20},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd21), cmd21},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd22), cmd22},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd23), cmd23},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd24), cmd24},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd25), cmd25},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd26), cmd26},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(cmd27), cmd27},
+
+ {DTYPE_DCS_WRITE, 1, 0, 0, 150, sizeof(exit_sleep), exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10, sizeof(display_on), display_on},
+
+ {DTYPE_DCS_WRITE1, 1, 0, 0, 150,
+ sizeof(config_MADCTL), config_MADCTL},
+
+ {DTYPE_DCS_WRITE, 1, 0, 0, 10, sizeof(write_ram), write_ram},
+};
+
+static char video0[6] = {
+ 0xF0, 0x55, 0xAA, 0x52,
+ 0x08, 0x01,
+};
+static char video1[4] = {
+ 0xBC, 0x00, 0xA0, 0x00,
+};
+static char video2[4] = {
+ 0xBD, 0x00, 0xA0, 0x00,
+};
+static char video3[3] = {
+ 0xBE, 0x00, 0x79,
+};
+static char video4[53] = {
+ 0xD1, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char video5[53] = {
+ 0xD2, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char video6[53] = {
+ 0xD3, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char video7[53] = {
+ 0xD4, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char video8[53] = {
+ 0xD5, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char video9[53] = {
+ 0xD6, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x32, 0x00,
+ 0x4F, 0x00, 0x65, 0x00,
+ 0x8B, 0x00, 0xA8, 0x00,
+ 0xD5, 0x00, 0xF7, 0x01,
+ 0x2B, 0x01, 0x54, 0x01,
+ 0x8E, 0x01, 0xBB, 0x01,
+ 0xBC, 0x01, 0xE3, 0x02,
+ 0x08, 0x02, 0x1C, 0x02,
+ 0x39, 0x02, 0x4F, 0x02,
+ 0x76, 0x02, 0xA3, 0x02,
+ 0xE3, 0x03, 0x12, 0x03,
+ 0x4C, 0x03, 0x66, 0x03,
+ 0x9A,
+};
+static char video10[4] = {
+ 0xB0, 0x0A, 0x0A, 0x0A,
+};
+static char video11[4] = {
+ 0xB1, 0x0A, 0x0A, 0x0A,
+};
+static char video12[4] = {
+ 0xBA, 0x24, 0x24, 0x24,
+};
+static char video13[4] = {
+ 0xB9, 0x24, 0x24, 0x24,
+};
+static char video14[4] = {
+ 0xB8, 0x24, 0x24, 0x24,
+};
+static char video15[6] = {
+ 0xF0, 0x55, 0xAA, 0x52,
+ 0x08, 0x00,
+};
+static char video16[2] = {
+ 0xB3, 0x00,
+};
+static char video17[2] = {
+ 0xB4, 0x10,
+};
+static char video18[2] = {
+ 0xB6, 0x02,
+};
+static char video19[3] = {
+ 0xB1, 0xFC, 0x06,
+};
+static char video20[4] = {
+ 0xBC, 0x05, 0x05, 0x05,
+};
+static char video21[3] = {
+ 0xB7, 0x20, 0x20,
+};
+static char video22[5] = {
+ 0xB8, 0x01, 0x03, 0x03,
+ 0x03,
+};
+static char video23[19] = {
+ 0xC8, 0x01, 0x00, 0x78,
+ 0x50, 0x78, 0x50, 0x78,
+ 0x50, 0x78, 0x50, 0xC8,
+ 0x3C, 0x3C, 0xC8, 0xC8,
+ 0x3C, 0x3C, 0xC8,
+};
+static char video24[6] = {
+ 0xBD, 0x01, 0x84, 0x07,
+ 0x31, 0x00,
+};
+static char video25[6] = {
+ 0xBE, 0x01, 0x84, 0x07,
+ 0x31, 0x00,
+};
+static char video26[6] = {
+ 0xBF, 0x01, 0x84, 0x07,
+ 0x31, 0x00,
+};
+static char video27[2] = {
+ 0x35, 0x00,
+};
+static struct dsi_cmd_desc nt35510_video_display_on_cmds[] = {
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video0), video0},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video1), video1},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video2), video2},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video3), video3},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video4), video4},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video5), video5},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video6), video6},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video7), video7},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video8), video8},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video9), video9},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video10), video10},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video11), video11},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video12), video12},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video13), video13},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video14), video14},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video15), video15},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video16), video16},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video17), video17},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video18), video18},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video19), video19},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video20), video20},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video21), video21},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video22), video22},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video23), video23},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video24), video24},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video25), video25},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video26), video26},
+ {DTYPE_GEN_LWRITE, 1, 0, 0, 50, sizeof(video27), video27},
+ {DTYPE_DCS_WRITE, 1, 0, 0, NT35510_SLEEP_OFF_DELAY, sizeof(exit_sleep),
+ exit_sleep},
+ {DTYPE_DCS_WRITE, 1, 0, 0, NT35510_DISPLAY_ON_DELAY, sizeof(display_on),
+ display_on},
+};
+
+static int mipi_nt35510_lcd_on(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+ struct mipi_panel_info *mipi;
+
+ mfd = platform_get_drvdata(pdev);
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi = &mfd->panel_info.mipi;
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+ nt35510_video_display_on_cmds,
+ ARRAY_SIZE(nt35510_video_display_on_cmds));
+ } else if (mipi->mode == DSI_CMD_MODE) {
+ mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+ nt35510_cmd_display_on_cmds,
+ ARRAY_SIZE(nt35510_cmd_display_on_cmds));
+ }
+
+ return 0;
+}
+
+static int mipi_nt35510_lcd_off(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ pr_debug("mipi_nt35510_lcd_off E\n");
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf, nt35510_display_off_cmds,
+ ARRAY_SIZE(nt35510_display_off_cmds));
+
+ pr_debug("mipi_nt35510_lcd_off X\n");
+ return 0;
+}
+
+static int __devinit mipi_nt35510_lcd_probe(struct platform_device *pdev)
+{
+ pr_debug("%s\n", __func__);
+
+ if (pdev->id == 0) {
+ mipi_nt35510_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = mipi_nt35510_lcd_probe,
+ .driver = {
+ .name = "mipi_NT35510",
+ },
+};
+
+static void mipi_nt35510_set_backlight(struct msm_fb_data_type *mfd)
+{
+ /* Add backlight changes later*/
+ return;
+}
+
+static struct msm_fb_panel_data nt35510_panel_data = {
+ .on = mipi_nt35510_lcd_on,
+ .off = mipi_nt35510_lcd_off,
+ .set_backlight = mipi_nt35510_set_backlight,
+};
+
+static int ch_used[3];
+
+static int mipi_nt35510_lcd_init(void)
+{
+ mipi_dsi_buf_alloc(&nt35510_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&nt35510_rx_buf, DSI_BUF_SIZE);
+
+ return platform_driver_register(&this_driver);
+}
+int mipi_nt35510_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel)
+{
+ struct platform_device *pdev = NULL;
+ int ret;
+
+ if ((channel >= 3) || ch_used[channel])
+ return -ENODEV;
+
+ ch_used[channel] = TRUE;
+
+ ret = mipi_nt35510_lcd_init();
+ if (ret) {
+ pr_err("mipi_nt35510_lcd_init() failed with ret %u\n", ret);
+ return ret;
+ }
+
+ pdev = platform_device_alloc("mipi_NT35510", (panel << 8)|channel);
+ if (!pdev)
+ return -ENOMEM;
+
+ nt35510_panel_data.panel_info = *pinfo;
+
+ ret = platform_device_add_data(pdev, &nt35510_panel_data,
+ sizeof(nt35510_panel_data));
+ if (ret) {
+ pr_debug("%s: platform_device_add_data failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ pr_debug("%s: platform_device_register failed!\n", __func__);
+ goto err_device_put;
+ }
+
+ return 0;
+
+err_device_put:
+ platform_device_put(pdev);
+ return ret;
+}
diff --git a/drivers/video/msm/mipi_NT35510.h b/drivers/video/msm/mipi_NT35510.h
new file mode 100644
index 0000000..5c81875
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MIPI_NT35510_H
+#define MIPI_NT35510_H
+
+int mipi_nt35510_device_register(struct msm_panel_info *pinfo,
+ u32 channel, u32 panel);
+
+#endif /* MIPI_NT35510_H */
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
new file mode 100644
index 0000000..2c4ee3e
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
@@ -0,0 +1,98 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_cmd_mode_phy_db = {
+ /* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+ /* regulator */
+ {0x03, 0x01, 0x01, 0x00},
+ /* timing */
+ {0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+ 0x18, 0x03, 0x04},
+ /* phy ctrl */
+ {0x7f, 0x00, 0x00, 0x00},
+ /* strength */
+ {0xbb, 0x02, 0x06, 0x00},
+ /* pll control */
+ {0x01, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+ 0x01, 0x0f, 0x07,
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+};
+
+static int mipi_cmd_nt35510_wvga_pt_init(void)
+{
+ int ret;
+
+ if (msm_fb_detect_client("mipi_cmd_nt35510_wvga"))
+ return 0;
+
+ pinfo.xres = 480;
+ pinfo.yres = 800;
+ pinfo.type = MIPI_CMD_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 100;
+ pinfo.lcdc.h_front_porch = 100;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 20;
+ pinfo.lcdc.v_front_porch = 20;
+ pinfo.lcdc.v_pulse_width = 1;
+
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.bl_max = 100;
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+ pinfo.clk_rate = 499000000;
+
+ pinfo.lcd.vsync_enable = TRUE;
+ pinfo.lcd.hw_vsync_mode = TRUE;
+ pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+
+ pinfo.mipi.mode = DSI_CMD_MODE;
+ pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+ pinfo.mipi.t_clk_post = 0x20;
+ pinfo.mipi.t_clk_pre = 0x2F;
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.te_sel = 1; /* TE from vsync gpio */
+ pinfo.mipi.interleave_max = 1;
+ pinfo.mipi.insert_dcs_cmd = TRUE;
+ pinfo.mipi.wr_mem_continue = 0x3c;
+ pinfo.mipi.wr_mem_start = 0x2c;
+ pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
+ pinfo.mipi.tx_eot_append = 0x01;
+ pinfo.mipi.rx_eot_ignore = 0x0;
+ pinfo.mipi.dlane_swap = 0x01;
+
+ ret = mipi_nt35510_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WVGA_PT);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_cmd_nt35510_wvga_pt_init);
diff --git a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
new file mode 100644
index 0000000..82e03b2
--- /dev/null
+++ b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
@@ -0,0 +1,108 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_fb.h"
+#include "mipi_dsi.h"
+#include "mipi_NT35510.h"
+
+static struct msm_panel_info pinfo;
+
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* DSI Bit Clock at 500 MHz, 2 lane, RGB888 */
+ /* regulator */
+ {0x03, 0x01, 0x01, 0x00},
+ /* timing */
+ {0xb9, 0x8e, 0x1f, 0x00, 0x98, 0x9c, 0x22, 0x90,
+ 0x18, 0x03, 0x04},
+ /* phy ctrl */
+ {0x7f, 0x00, 0x00, 0x00},
+ /* strength */
+ {0xbb, 0x02, 0x06, 0x00},
+ /* pll control */
+ {0x00, 0xec, 0x31, 0xd2, 0x00, 0x40, 0x37, 0x62,
+ 0x01, 0x0f, 0x07,
+ 0x05, 0x14, 0x03, 0x0, 0x0, 0x0, 0x20, 0x0, 0x02, 0x0},
+};
+
+static int mipi_video_nt35510_wvga_pt_init(void)
+{
+ int ret;
+
+ if (msm_fb_detect_client("mipi_video_nt35510_wvga"))
+ return 0;
+
+ pinfo.xres = 480;
+ pinfo.yres = 800;
+ pinfo.type = MIPI_VIDEO_PANEL;
+ pinfo.pdest = DISPLAY_1;
+ pinfo.wait_cycle = 0;
+ pinfo.bpp = 24;
+ pinfo.lcdc.h_back_porch = 100;
+ pinfo.lcdc.h_front_porch = 100;
+ pinfo.lcdc.h_pulse_width = 8;
+ pinfo.lcdc.v_back_porch = 20;
+ pinfo.lcdc.v_front_porch = 20;
+ pinfo.lcdc.v_pulse_width = 1;
+ pinfo.lcdc.border_clr = 0; /* blk */
+ pinfo.lcdc.underflow_clr = 0xff; /* blue */
+ /* number of dot_clk cycles HSYNC active edge is
+ delayed from VSYNC active edge */
+ pinfo.lcdc.hsync_skew = 0;
+ pinfo.clk_rate = 499000000;
+ pinfo.bl_max = 100; /*16; CHECK THIS!!!*/
+ pinfo.bl_min = 1;
+ pinfo.fb_num = 2;
+
+ pinfo.mipi.mode = DSI_VIDEO_MODE;
+ /* send HSA and HE following VS/VE packet */
+ pinfo.mipi.pulse_mode_hsa_he = TRUE;
+ pinfo.mipi.hfp_power_stop = TRUE; /* LP-11 during the HFP period */
+ pinfo.mipi.hbp_power_stop = TRUE; /* LP-11 during the HBP period */
+ pinfo.mipi.hsa_power_stop = TRUE; /* LP-11 during the HSA period */
+ /* LP-11 or let Command Mode Engine send packets in
+ HS or LP mode for the BLLP of the last line of a frame */
+ pinfo.mipi.eof_bllp_power_stop = TRUE;
+ /* LP-11 or let Command Mode Engine send packets in
+ HS or LP mode for packets sent during BLLP period */
+ pinfo.mipi.bllp_power_stop = TRUE;
+
+ pinfo.mipi.traffic_mode = DSI_BURST_MODE;
+ pinfo.mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
+ pinfo.mipi.vc = 0;
+ pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB; /* RGB */
+ pinfo.mipi.data_lane0 = TRUE;
+ pinfo.mipi.data_lane1 = TRUE;
+
+ pinfo.mipi.t_clk_post = 0x20;
+ pinfo.mipi.t_clk_pre = 0x2f;
+
+ pinfo.mipi.stream = 0; /* dma_p */
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+ pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.frame_rate = 60; /* FIXME */
+
+ pinfo.mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+ pinfo.mipi.dlane_swap = 0x01;
+ /* append EOT at the end of data burst */
+ pinfo.mipi.tx_eot_append = 0x01;
+
+ ret = mipi_nt35510_device_register(&pinfo, MIPI_DSI_PRIM,
+ MIPI_DSI_PANEL_WVGA_PT);
+
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_video_nt35510_wvga_pt_init);
diff --git a/drivers/video/msm/mipi_chimei_wuxga.c b/drivers/video/msm/mipi_chimei_wuxga.c
new file mode 100644
index 0000000..c63df46
--- /dev/null
+++ b/drivers/video/msm/mipi_chimei_wuxga.c
@@ -0,0 +1,196 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+ * Chimei WUXGA LVDS Panel driver.
+ * The panel model is N101JSF-L21.
+ *
+ * The panel interface includes:
+ * 1. LVDS input for video (clock & data).
+ * 2. few configuration pins to control 3D module: Enable, Mode (2D/3D).
+ * 3. Backlight LED control (PWM 200 HZ).
+ *
+ * This panel is controled via the Toshiba DSI-to-LVDS bridge.
+ *
+ */
+
+/* #define DEBUG 1 */
+
+#include "msm_fb.h"
+#include "msm_fb_panel.h"
+#include "mipi_dsi.h"
+#include "mipi_tc358764_dsi2lvds.h"
+
+#define MHZ (1000*1000)
+
+/**
+ * Panel info parameters.
+ * The panel info is passed to the mipi framebuffer driver.
+ */
+static struct msm_panel_info chimei_wuxga_pinfo;
+
+/**
+ * The mipi_dsi_phy_ctrl is calculated according to the
+ * "dsi_timing_program.xlsm" excel sheet.
+ * Output is based on: 1200x1920, RGB565, 4 lanes , 58 frames
+ * per second.
+ */
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* DSIPHY_REGULATOR_CTRL */
+ .regulator = {0x03, 0x0a, 0x04, 0x00, 0x20}, /* common 8960 */
+ /* DSIPHY_CTRL */
+ .ctrl = {0x5f, 0x00, 0x00, 0x10}, /* common 8960 */
+ /* DSIPHY_STRENGTH_CTRL */
+ .strength = {0xff, 0x00, 0x06, 0x00}, /* common 8960 */
+ /* DSIPHY_TIMING_CTRL */
+ .timing = { 0xC9, 0x92, 0x29, /* panel specific */
+ 0, /* DSIPHY_TIMING_CTRL_3 = 0 */
+ 0x2E, 0x9B, 0x2C, 0x94, 0x2E, 0x03, 0x04}, /* panel specific */
+
+ /* DSIPHY_PLL_CTRL */
+ .pll = { 0x00, /* common 8960 */
+ /* VCO */
+ 0x32, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
+ 0x00, 0x50, 0x48, 0x63,
+ 0x77, 0x88, 0x99, /* Auto update by dsi-mipi driver */
+ 0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
+ 0x00, 0x20, 0x00, 0x01 }, /* common 8960 */
+};
+
+/**
+ * Module init.
+ *
+ * Register the panel-info.
+ *
+ * Some parameters are from the panel datasheet
+ * and other are *calculated* by the "dsi_timing_program.xlsm"
+ * excel file
+ *
+ * @return int
+ */
+static int __init mipi_chimei_wuxga_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo = &chimei_wuxga_pinfo;
+
+ if (msm_fb_detect_client("mipi_video_chimei_wuxga"))
+ return 0;
+
+ pr_info("mipi-dsi chimei wuxga (1200x1920) driver ver 1.0.\n");
+
+ /* Portrait */
+ pinfo->xres = 1200;
+ pinfo->yres = 1920;
+ pinfo->type = MIPI_VIDEO_PANEL;
+ pinfo->pdest = DISPLAY_1; /* Primary Display */
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24; /* RGB565 requires 24 bits-per-pixel :-O */
+ pinfo->fb_num = 2; /* using two frame buffers */
+
+ /*
+ * The CMI panel requires 80 MHZ LVDS-CLK.
+ * The D2L bridge drives the LVDS-CLK from the DSI-CLK.
+ * The DSI-CLK = bitclk/2, 640 MHZ/2= 320 MHZ.
+ * LVDS-CLK = DSI-CLK/4 , 320 MHZ/4= 80 MHZ.
+ */
+
+ pinfo->clk_rate = 640 * MHZ ; /* bitclk Calculated */
+
+ /*
+ * this panel is operated by DE,
+ * vsycn and hsync are ignored
+ */
+
+ pinfo->lcdc.h_front_porch = 16; /* thfp */
+ pinfo->lcdc.h_back_porch = 160; /* thb */
+ pinfo->lcdc.h_pulse_width = 32; /* thpw */
+
+ pinfo->lcdc.v_front_porch = 0; /* tvfp */
+ pinfo->lcdc.v_back_porch = 26; /* tvb */
+ pinfo->lcdc.v_pulse_width = 6; /* tvpw */
+
+ pinfo->lcdc.border_clr = 0; /* black */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+
+ pinfo->lcdc.hsync_skew = 0;
+
+ /* Backlight levels - controled via PMIC pwm gpio */
+ pinfo->bl_max = 15;
+ pinfo->bl_min = 1;
+
+ /* mipi - general */
+ pinfo->mipi.vc = 0; /* virtual channel */
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo->mipi.tx_eot_append = true;
+ pinfo->mipi.t_clk_post = 34; /* Calculated */
+ pinfo->mipi.t_clk_pre = 69; /* Calculated */
+
+ pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ /* Four lanes are recomended for 1920x1200 at 60 frames per second */
+ pinfo->mipi.frame_rate = 45; /* 45 frames per second */
+ pinfo->mipi.data_lane0 = true;
+ pinfo->mipi.data_lane1 = true;
+ pinfo->mipi.data_lane2 = true;
+ pinfo->mipi.data_lane3 = true;
+
+ pinfo->mipi.mode = DSI_VIDEO_MODE;
+ /*
+ * Note: The CMI panel input is RGB888,
+ * thus the DSI-to-LVDS bridge output is RGB888.
+ * This parameter selects the DSI-Core output to the bridge.
+ */
+ pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+
+ /* mipi - video mode */
+ pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
+ pinfo->mipi.pulse_mode_hsa_he = false; /* sync mode */
+
+ pinfo->mipi.hfp_power_stop = false;
+ pinfo->mipi.hbp_power_stop = false;
+ pinfo->mipi.hsa_power_stop = false;
+ pinfo->mipi.eof_bllp_power_stop = false;
+ pinfo->mipi.bllp_power_stop = false;
+
+ /* mipi - command mode */
+ pinfo->mipi.te_sel = 1; /* TE from vsycn gpio */
+ pinfo->mipi.interleave_max = 1;
+ /* The bridge supports only Generic Read/Write commands */
+ pinfo->mipi.insert_dcs_cmd = false;
+ pinfo->mipi.wr_mem_continue = 0;
+ pinfo->mipi.wr_mem_start = 0;
+ pinfo->mipi.stream = false; /* dma_p */
+ pinfo->mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+ pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ /*
+ * toshiba d2l chip does not need max_pkt_size dcs cmd
+ * client reply len is directly configure through
+ * RDPKTLN register (0x0404)
+ */
+ pinfo->mipi.no_max_pkt_size = 1;
+ pinfo->mipi.force_clk_lane_hs = 1;
+
+ pinfo->is_3d_panel = FB_TYPE_3D_PANEL;
+
+ ret = mipi_tc358764_dsi2lvds_register(pinfo, MIPI_DSI_PRIM, 1);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_chimei_wuxga_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Chimei WUXGA LVDS Panel driver");
+MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index caa4114..ed0dee4 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -461,6 +461,7 @@
struct mipi_panel_info *mipi;
struct platform_device *current_pdev;
static struct mipi_dsi_phy_ctrl *phy_settings;
+ static char dlane_swap;
if (pdev->id == 0) {
mipi_novatek_pdata = pdev->dev.platform_data;
@@ -471,6 +472,11 @@
}
if (mipi_novatek_pdata
+ && mipi_novatek_pdata->dlane_swap) {
+ dlane_swap = (mipi_novatek_pdata->dlane_swap);
+ }
+
+ if (mipi_novatek_pdata
&& mipi_novatek_pdata->fpga_3d_config_addr)
mipi_novatek_3d_init(mipi_novatek_pdata
->fpga_3d_config_addr, mipi_novatek_pdata->fpga_ctrl_mode);
@@ -499,6 +505,9 @@
if (phy_settings != NULL)
mipi->dsi_phy_db = phy_settings;
+
+ if (dlane_swap)
+ mipi->dlane_swap = dlane_swap;
}
return 0;
}
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
index 8055bd0..fcb5163 100644
--- a/drivers/video/msm/mipi_tc358764_dsi2lvds.c
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -68,7 +68,9 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/pwm.h>
+#include <linux/gpio.h>
#include "msm_fb.h"
+#include "mdp4.h"
#include "mipi_dsi.h"
#include "mipi_tc358764_dsi2lvds.h"
@@ -186,7 +188,11 @@
#define DEBUG01 0x05A4 /* LVDS Data */
/* PWM */
-#define PWM_FREQ_HZ (66*1000) /* 66 KHZ */
+static u32 d2l_pwm_freq_hz = (66*1000);
+
+/* 1366x768 uses pwm at 66 KHZ */
+/* 1200x1920 uses pwm at 25 KHZ */
+#define PWM_FREQ_HZ (d2l_pwm_freq_hz)
#define PWM_LEVEL 15
#define PWM_PERIOD_USEC (USEC_PER_SEC / PWM_FREQ_HZ)
#define PWM_DUTY_LEVEL (PWM_PERIOD_USEC / PWM_LEVEL)
@@ -213,10 +219,17 @@
static struct dsi_buf d2l_rx_buf;
static int led_pwm;
static struct pwm_device *bl_pwm;
+static struct pwm_device *tn_pwm;
static int bl_level;
static u32 d2l_gpio_out_mask;
static u32 d2l_gpio_out_val;
+static u32 d2l_3d_gpio_enable;
+static u32 d2l_3d_gpio_mode;
+static int d2l_enable_3d;
+
static int mipi_d2l_init(void);
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+ bool enable, bool mode);
/**
* Read a bridge register
@@ -236,7 +249,7 @@
mipi_dsi_buf_init(&d2l_tx_buf);
mipi_dsi_buf_init(&d2l_rx_buf);
- /* mutex had been acquried at dsi_on */
+ /* mutex had been acquired at mipi_dsi_on */
len = mipi_dsi_cmds_rx(mfd, &d2l_tx_buf, &d2l_rx_buf,
&cmd_read_reg, len);
@@ -247,7 +260,6 @@
pr_debug("%s: reg=0x%x.data=0x%08x.\n", __func__, reg, data);
-
return data;
}
@@ -256,9 +268,9 @@
*
* @param mfd
*
- * @return register data value
+ * @return int
*/
-static u32 mipi_d2l_write_reg(struct msm_fb_data_type *mfd, u16 reg, u32 data)
+static int mipi_d2l_write_reg(struct msm_fb_data_type *mfd, u16 reg, u32 data)
{
struct wr_cmd_payload payload;
struct dsi_cmd_desc cmd_write_reg = {
@@ -268,35 +280,25 @@
payload.addr = reg;
payload.data = data;
- /* mutex had been acquried at dsi_on */
+ /* mutex had been acquired at mipi_dsi_on */
mipi_dsi_cmds_tx(mfd, &d2l_tx_buf, &cmd_write_reg, 1);
pr_debug("%s: reg=0x%x. data=0x%x.\n", __func__, reg, data);
- return data;
+ return 0;
}
-/*
+static void mipi_d2l_read_status(struct msm_fb_data_type *mfd)
+{
+ mipi_d2l_read_reg(mfd, DSI_LANESTATUS0); /* 0x214 */
+ mipi_d2l_read_reg(mfd, DSI_LANESTATUS1); /* 0x218 */
+ mipi_d2l_read_reg(mfd, DSI_INTSTATUS); /* 0x220 */
+ mipi_d2l_read_reg(mfd, SYSSTAT); /* 0x500 */
+}
+
+/**
* Init the D2L bridge via the DSI interface for Video.
*
- * Register Addr Value
- * ===================================================
- * PPI_TX_RX_TA 0x013C 0x00040004
- * PPI_LPTXTIMECNT 0x0114 0x00000004
- * PPI_D0S_CLRSIPOCOUNT 0x0164 0x00000003
- * PPI_D1S_CLRSIPOCOUNT 0x0168 0x00000003
- * PPI_D2S_CLRSIPOCOUNT 0x016C 0x00000003
- * PPI_D3S_CLRSIPOCOUNT 0x0170 0x00000003
- * PPI_LANEENABLE 0x0134 0x0000001F
- * DSI_LANEENABLE 0x0210 0x0000001F
- * PPI_STARTPPI 0x0104 0x00000001
- * DSI_STARTDSI 0x0204 0x00000001
- * VPCTRL 0x0450 0x01000120
- * HTIM1 0x0454 0x002C0028
- * VTIM1 0x045C 0x001E0008
- * VFUEN 0x0464 0x00000001
- * LVCFG 0x049C 0x00000001
- *
* VPCTRL.EVTMODE (0x20) configuration bit is needed to determine whether
* video timing information is delivered in pulse mode or event mode.
* In pulse mode, both Sync Start and End packets are required.
@@ -304,15 +306,22 @@
*
* @param mfd
*
- * @return register data value
+ * @return int
*/
static int mipi_d2l_dsi_init_sequence(struct msm_fb_data_type *mfd)
{
struct mipi_panel_info *mipi = &mfd->panel_info.mipi;
u32 lanes_enable;
u32 vpctrl;
- u32 htime1 = 0x002C0028;
- u32 vtime1 = 0x001E0008;
+ u32 htime1;
+ u32 vtime1;
+ u32 ppi_tx_rx_ta; /* BTA Bus-Turn-Around */
+ u32 lvcfg;
+ u32 hbpr; /* Horizontal Back Porch */
+ u32 hpw; /* Horizontal Pulse Width */
+ u32 vbpr; /* Vertical Back Porch */
+ u32 vpw; /* Vertical Pulse Width */
+ bool vesa_rgb888 = false;
lanes_enable = 0x01; /* clock-lane enable */
lanes_enable |= (mipi->data_lane0 << 1);
@@ -330,25 +339,57 @@
return -EINVAL;
}
+ if (mfd->panel_info.clk_rate > 800*1000*1000) {
+ pr_err("%s.unsupported clk_rate %d.\n",
+ __func__, mfd->panel_info.clk_rate);
+ return -EINVAL;
+ }
+
+ pr_debug("%s.xres=%d.yres=%d.\n",
+ __func__, mfd->panel_info.xres, mfd->panel_info.yres);
+
+ hbpr = mfd->panel_info.lcdc.h_back_porch;
+ hpw = mfd->panel_info.lcdc.h_pulse_width;
+ vbpr = mfd->panel_info.lcdc.v_back_porch;
+ vpw = mfd->panel_info.lcdc.v_pulse_width;
+
+ htime1 = (hbpr << 16) + hpw;
+ vtime1 = (vbpr << 16) + vpw;
+ lvcfg = 0x0003; /* PCLK=DCLK/3, Dual Link, LVEN */
+ vpctrl = 0x01000120; /* Output RGB888 , Event-Mode , */
+ ppi_tx_rx_ta = 0x00040004;
+
+ if (mfd->panel_info.xres == 1366) {
+ ppi_tx_rx_ta = 0x00040004;
+ lvcfg = 0x01; /* LVEN */
+ vesa_rgb888 = true;
+ }
+
+ if (mfd->panel_info.xres == 1200) {
+ lvcfg = 0x0103; /* PCLK=DCLK/4, Dual Link, LVEN */
+ vesa_rgb888 = true;
+ }
+
pr_debug("%s.htime1=0x%x.\n", __func__, htime1);
pr_debug("%s.vtime1=0x%x.\n", __func__, vtime1);
pr_debug("%s.vpctrl=0x%x.\n", __func__, vpctrl);
- pr_debug("%s.lanes_enable=0x%x.\n", __func__, lanes_enable);
-
+ pr_debug("%s.lvcfg=0x%x.\n", __func__, lvcfg);
mipi_d2l_write_reg(mfd, SYSRST, 0xFF);
msleep(30);
- /* VESA format instead of JEIDA format for RGB888 */
- mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
- mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
- mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
- mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
- mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
- mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
- mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);
+ if (vesa_rgb888) {
+ /* VESA format instead of JEIDA format for RGB888 */
+ mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
+ mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
+ mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
+ mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
+ mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
+ mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
+ mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);
+ }
- mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, 0x00040004); /* BTA */
+ mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, ppi_tx_rx_ta); /* BTA */
mipi_d2l_write_reg(mfd, PPI_LPTXTIMECNT, 0x00000004);
mipi_d2l_write_reg(mfd, PPI_D0S_CLRSIPOCOUNT, 0x00000003);
mipi_d2l_write_reg(mfd, PPI_D1S_CLRSIPOCOUNT, 0x00000003);
@@ -363,7 +404,7 @@
mipi_d2l_write_reg(mfd, HTIM1, htime1);
mipi_d2l_write_reg(mfd, VTIM1, vtime1);
mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
- mipi_d2l_write_reg(mfd, LVCFG, 0x00000001); /* Enables LVDS tx */
+ mipi_d2l_write_reg(mfd, LVCFG, lvcfg); /* Enables LVDS tx */
return 0;
}
@@ -400,6 +441,35 @@
return ret;
}
+ return 0;
+}
+
+/**
+ * Set TN CLK.
+ *
+ * @param pwm
+ * @param level
+ *
+ * @return int
+ */
+static int mipi_d2l_set_tn_clk(struct pwm_device *pwm, u32 usec)
+{
+ int ret = 0;
+
+ pr_debug("%s: usec=%d.\n", __func__, usec);
+
+ ret = pwm_config(pwm, usec/2 , usec);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
+ return ret;
+ }
+
+ ret = pwm_enable(pwm);
+ if (ret) {
+ pr_err("%s: pwm_enable() failed err=%d\n",
+ __func__, ret);
+ return ret;
+ }
return 0;
}
@@ -446,9 +516,14 @@
return ret;
mipi_d2l_write_reg(mfd, GPIOC, d2l_gpio_out_mask);
- /* Set GPIOs: gpio#4=U/D=0 , gpio#3=L/R=1 , gpio#2,1=CABC=0. */
+ /* Set gpio#4=U/D=0, gpio#3=L/R=1 , gpio#2,1=CABC=0, gpio#0=NA. */
mipi_d2l_write_reg(mfd, GPIOO, d2l_gpio_out_val);
+ if (mfd->panel_info.xres == 1366)
+ d2l_pwm_freq_hz = (66*1000);
+ else
+ d2l_pwm_freq_hz = (25*1000);
+
if (bl_level == 0)
bl_level = PWM_LEVEL * 2 / 3 ; /* Default ON value */
@@ -460,6 +535,10 @@
__func__, ret);
}
+ mipi_d2l_read_status(mfd);
+
+ mipi_d2l_enable_3d(mfd, false, false);
+
pr_info("%s.ret=%d.\n", __func__, ret);
return ret;
@@ -510,6 +589,98 @@
.set_backlight = mipi_d2l_set_backlight,
};
+static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
+ bool enable, bool mode)
+{
+ u32 tn_usec = 1000000 / 66; /* 66 HZ */
+
+ pr_debug("%s.enable=%d.mode=%d.\n", __func__, enable, mode);
+
+ gpio_direction_output(d2l_3d_gpio_enable, enable);
+ gpio_direction_output(d2l_3d_gpio_mode, mode);
+
+ mipi_d2l_set_tn_clk(tn_pwm, tn_usec);
+
+ return 0;
+}
+
+static ssize_t mipi_d2l_enable_3d_read(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf((char *)buf, sizeof(buf), "%u\n", d2l_enable_3d);
+}
+
+static ssize_t mipi_d2l_enable_3d_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = -1;
+ u32 data = 0;
+
+ if (sscanf((char *)buf, "%u", &data) != 1) {
+ dev_err(dev, "%s. Invalid input.\n", __func__);
+ ret = -EINVAL;
+ } else {
+ d2l_enable_3d = data;
+ if (data == 1) /* LANDSCAPE */
+ mipi_d2l_enable_3d(d2l_mfd, true, true);
+ else if (data == 2) /* PORTRAIT */
+ mipi_d2l_enable_3d(d2l_mfd, true, false);
+ else if (data == 0)
+ mipi_d2l_enable_3d(d2l_mfd, false, false);
+ else
+ pr_err("%s.Invalid value=%d.\n", __func__, data);
+ }
+
+ return count;
+}
+
+static struct device_attribute mipi_d2l_3d_barrier_attributes[] = {
+ __ATTR(enable_3d_barrier, 0666,
+ mipi_d2l_enable_3d_read,
+ mipi_d2l_enable_3d_write),
+};
+
+static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev)
+{
+ int ret;
+
+ pr_debug("%s.d2l_3d_gpio_enable=%d.\n", __func__, d2l_3d_gpio_enable);
+ pr_debug("%s.d2l_3d_gpio_mode=%d.\n", __func__, d2l_3d_gpio_mode);
+
+ ret = device_create_file(dev, mipi_d2l_3d_barrier_attributes);
+ if (ret) {
+ pr_err("%s.failed to create 3D sysfs.\n", __func__);
+ goto err_device_create_file;
+ }
+
+ ret = gpio_request(d2l_3d_gpio_enable, "d2l_3d_gpio_enable");
+ if (ret) {
+ pr_err("%s.failed to get d2l_3d_gpio_enable=%d.\n",
+ __func__, d2l_3d_gpio_enable);
+ goto err_d2l_3d_gpio_enable;
+ }
+
+ ret = gpio_request(d2l_3d_gpio_mode, "d2l_3d_gpio_mode");
+ if (ret) {
+ pr_err("%s.failed to get d2l_3d_gpio_mode=%d.\n",
+ __func__, d2l_3d_gpio_mode);
+ goto err_d2l_3d_gpio_mode;
+ }
+
+ return 0;
+
+err_d2l_3d_gpio_mode:
+ gpio_free(d2l_3d_gpio_enable);
+err_d2l_3d_gpio_enable:
+ device_remove_file(dev, mipi_d2l_3d_barrier_attributes);
+err_device_create_file:
+
+ return ret;
+}
+
/**
* Probe for device.
*
@@ -530,7 +701,6 @@
pr_debug("%s.id=%d.\n", __func__, pdev->id);
if (pdev->id == 0) {
- /* d2l_common_pdata = platform_get_drvdata(pdev); */
d2l_common_pdata = pdev->dev.platform_data;
if (d2l_common_pdata == NULL) {
@@ -541,6 +711,8 @@
led_pwm = d2l_common_pdata->gpio_num[0];
d2l_gpio_out_mask = d2l_common_pdata->gpio_num[1] >> 8;
d2l_gpio_out_val = d2l_common_pdata->gpio_num[1] & 0xFF;
+ d2l_3d_gpio_enable = d2l_common_pdata->gpio_num[2];
+ d2l_3d_gpio_mode = d2l_common_pdata->gpio_num[3];
mipi_dsi_buf_alloc(&d2l_tx_buf, DSI_BUF_SIZE);
mipi_dsi_buf_alloc(&d2l_rx_buf, DSI_BUF_SIZE);
@@ -567,10 +739,20 @@
}
} else {
- pr_info("%s. led_pwm is invalid.\n", __func__);
+ pr_err("%s. led_pwm is invalid.\n", __func__);
}
- /* pinfo = platform_get_drvdata(pdev); */
+ tn_pwm = pwm_request(1, "3D_TN_clk");
+ if (tn_pwm == NULL || IS_ERR(tn_pwm)) {
+ pr_err("%s pwm_request() failed.id=%d.tn_pwm=%d.\n",
+ __func__, 1, (int) tn_pwm);
+ tn_pwm = NULL;
+ return -EIO;
+ } else {
+ pr_debug("%s.pwm_request() ok.pwm-id=%d.\n", __func__, 1);
+
+ }
+
pinfo = pdev->dev.platform_data;
if (pinfo == NULL) {
@@ -584,6 +766,9 @@
msm_fb_add_device(pdev);
+ if (pinfo->is_3d_panel)
+ mipi_dsi_3d_barrier_sysfs_register(&(pdev->dev));
+
return ret;
}
@@ -667,6 +852,7 @@
static int mipi_d2l_init(void)
{
pr_debug("%s.\n", __func__);
+
return platform_driver_register(&d2l_driver);
}
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 42fa2ba..489e6d2 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1520,8 +1520,8 @@
pdata->set_backlight(mfd);
bl_level_old = unset_bl_level;
up(&mfd->sem);
+ bl_updated = 1;
}
- bl_updated = 1;
}
++mfd->panel_info.frame_count;
@@ -2624,8 +2624,8 @@
pdata->set_backlight(mfd);
bl_level_old = unset_bl_level;
up(&mfd->sem);
+ bl_updated = 1;
}
- bl_updated = 1;
}
return ret;
diff --git a/include/linux/leds-pm8xxx.h b/include/linux/leds-pm8xxx.h
index 3f31498..18e6398 100644
--- a/include/linux/leds-pm8xxx.h
+++ b/include/linux/leds-pm8xxx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,8 @@
PM8XXX_ID_LED_2,
PM8XXX_ID_FLASH_LED_0,
PM8XXX_ID_FLASH_LED_1,
+ PM8XXX_ID_WLED,
+ PM8XXX_ID_MAX,
};
/**
@@ -50,6 +52,48 @@
PM8XXX_LED_MODE_DTEST4
};
+/* current boost limit */
+enum wled_current_bost_limit {
+ WLED_CURR_LIMIT_105mA,
+ WLED_CURR_LIMIT_385mA,
+ WLED_CURR_LIMIT_525mA,
+ WLED_CURR_LIMIT_805mA,
+ WLED_CURR_LIMIT_980mA,
+ WLED_CURR_LIMIT_1260mA,
+ WLED_CURR_LIMIT_1400mA,
+ WLED_CURR_LIMIT_1680mA,
+};
+
+/* over voltage protection threshold */
+enum wled_ovp_threshold {
+ WLED_OVP_35V,
+ WLED_OVP_32V,
+ WLED_OVP_29V,
+ WLED_OVP_37V,
+};
+
+/**
+ * wled_config_data - wled configuration data
+ * @num_strings - number of wled strings supported
+ * @ovp_val - over voltage protection threshold
+ * @boost_curr_lim - boot current limit
+ * @cp_select - high pole capacitance
+ * @ctrl_delay_us - delay in activation of led
+ * @dig_mod_gen_en - digital module generator
+ * @cs_out_en - current sink output enable
+ * @op_fdbck - selection of output as feedback for the boost
+ */
+struct wled_config_data {
+ u8 num_strings;
+ u8 ovp_val;
+ u8 boost_curr_lim;
+ u8 cp_select;
+ u8 ctrl_delay_us;
+ bool dig_mod_gen_en;
+ bool cs_out_en;
+ bool op_fdbck;
+};
+
/**
* pm8xxx_led_config - led configuration parameters
* @id - LED id
@@ -57,6 +101,7 @@
* @max_current - maximum current that LED can sustain
* @pwm_channel - PWM channel ID the LED is driven to
* @pwm_period_us - PWM period value in micro seconds
+ * @default_state - default state of the led
* @pwm_duty_cycles - PWM duty cycle information
*/
struct pm8xxx_led_config {
@@ -65,7 +110,9 @@
u16 max_current;
int pwm_channel;
u32 pwm_period_us;
+ bool default_state;
struct pm8xxx_pwm_duty_cycles *pwm_duty_cycles;
+ struct wled_config_data *wled_cfg;
};
/**
diff --git a/include/linux/mfd/pm8xxx/pm8038.h b/include/linux/mfd/pm8xxx/pm8038.h
index 203095a..4d3c78f 100644
--- a/include/linux/mfd/pm8xxx/pm8038.h
+++ b/include/linux/mfd/pm8xxx/pm8038.h
@@ -30,6 +30,7 @@
#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/pm8921-bms.h>
+#include <linux/leds-pm8xxx.h>
#include <linux/mfd/pm8xxx/ccadc.h>
#define PM8038_CORE_DEV_NAME "pm8038-core"
@@ -75,6 +76,7 @@
struct pm8921_charger_platform_data *charger_pdata;
struct pm8921_bms_platform_data *bms_pdata;
struct pm8xxx_adc_platform_data *adc_pdata;
+ struct pm8xxx_led_platform_data *leds_pdata;
struct pm8xxx_ccadc_platform_data *ccadc_pdata;
};
diff --git a/include/linux/mfd/wcd9310/core.h b/include/linux/mfd/wcd9310/core.h
index 982803d..8605ac6 100644
--- a/include/linux/mfd/wcd9310/core.h
+++ b/include/linux/mfd/wcd9310/core.h
@@ -14,6 +14,7 @@
#define __MFD_TABLA_CORE_H__
#include <linux/interrupt.h>
+#include <linux/wakelock.h>
#define TABLA_NUM_IRQ_REGS 3
@@ -55,6 +56,12 @@
TABLA_NUM_IRQS,
};
+enum tabla_pm_state {
+ TABLA_PM_SLEEPABLE,
+ TABLA_PM_AWAKE,
+ TABLA_PM_ASLEEP,
+};
+
struct tabla {
struct device *dev;
struct slim_device *slim;
@@ -78,23 +85,33 @@
int bytes, void *src, bool interface_reg);
struct regulator_bulk_data *supplies;
+
+ enum tabla_pm_state pm_state;
+ struct mutex pm_lock;
+ /* pm_wq notifies change of pm_state */
+ wait_queue_head_t pm_wq;
+ struct wake_lock wlock;
+ int wlock_holders;
};
int tabla_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_reg_write(struct tabla *tabla, unsigned short reg,
- u8 val);
+int tabla_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
int tabla_interface_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg,
- u8 val);
-int tabla_bulk_read(struct tabla *tabla, unsigned short reg,
- int count, u8 *buf);
-int tabla_bulk_write(struct tabla *tabla, unsigned short reg,
- int count, u8 *buf);
+int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
+int tabla_bulk_read(struct tabla *tabla, unsigned short reg, int count,
+ u8 *buf);
+int tabla_bulk_write(struct tabla *tabla, unsigned short reg, int count,
+ u8 *buf);
int tabla_irq_init(struct tabla *tabla);
void tabla_irq_exit(struct tabla *tabla);
int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
int tabla_get_intf_type(void);
+void tabla_lock_sleep(struct tabla *tabla);
+void tabla_unlock_sleep(struct tabla *tabla);
+enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
+ enum tabla_pm_state n);
+
static inline int tabla_request_irq(struct tabla *tabla, int irq,
irq_handler_t handler, const char *name,
void *data)
diff --git a/include/linux/mfd/wcd9310/wcd9310-slimslave.h b/include/linux/mfd/wcd9310/wcd9310-slimslave.h
new file mode 100644
index 0000000..0bbf96f
--- /dev/null
+++ b/include/linux/mfd/wcd9310/wcd9310-slimslave.h
@@ -0,0 +1,102 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __WCD9310_SLIMSLAVE_H_
+#define __WCD9310_SLIMSLAVE_H_
+
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9310/core.h>
+
+/* Local to the core only */
+#define SLIM_MAX_RX_PORTS 7
+#define SLIM_MAX_TX_PORTS 10
+
+/* Channel numbers to be used for each port */
+enum {
+ SLIM_TX_1 = 128,
+ SLIM_TX_2 = 129,
+ SLIM_TX_3 = 130,
+ SLIM_TX_4 = 131,
+ SLIM_TX_5 = 132,
+ SLIM_TX_6 = 133,
+ SLIM_TX_7 = 134,
+ SLIM_TX_8 = 135,
+ SLIM_TX_9 = 136,
+ SLIM_TX_10 = 137,
+ SLIM_RX_1 = 138,
+ SLIM_RX_2 = 139,
+ SLIM_RX_3 = 140,
+ SLIM_RX_4 = 141,
+ SLIM_RX_5 = 142,
+ SLIM_RX_6 = 143,
+ SLIM_RX_7 = 144,
+ SLIM_MAX = 145
+};
+
+/*
+ * client is expected to give port ids in the range of 1-10 for Tx ports and
+ * 1-7 for Rx ports, we need to add offset for getting the absolute slave
+ * port id before configuring the HW
+ */
+#define SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS 10
+#define SB_PGD_OFFSET_OF_TX_SLAVE_DEV_PORTS -1
+#define SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS 7
+#define SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS 9
+
+/* below details are taken from SLIMBUS slave SWI */
+#define SB_PGD_PORT_BASE 0x000
+
+#define SB_PGD_PORT_CFG_BYTE_ADDR(port_num) \
+ (SB_PGD_PORT_BASE + 0x040 + 1*port_num)
+
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0(port_num) \
+ (SB_PGD_PORT_BASE + 0x100 + 4*port_num)
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0_START_PORT_ID 0
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID 7
+
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1(port_num) \
+ (SB_PGD_PORT_BASE + 0x101 + 4*port_num)
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID 8
+#define SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID 9
+
+#define SB_PGD_RX_PORT_MULTI_CHANNEL_0(port_num) \
+ (SB_PGD_PORT_BASE + 0x180 + 4*port_num)
+#define SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID 10
+#define SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID 16
+
+/* slave port water mark level
+ * (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes)
+ */
+#define SLAVE_PORT_WATER_MARK_VALUE 2
+#define SLAVE_PORT_WATER_MARK_SHIFT 1
+#define SLAVE_PORT_ENABLE 1
+#define SLAVE_PORT_DISABLE 0
+
+#define BASE_CH_NUM 128
+
+
+int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la);
+
+int tabla_deinit_slimslave(struct tabla *tabla);
+
+int tabla_cfg_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+ unsigned int tot_ch, unsigned int rate);
+int tabla_cfg_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+ unsigned int tot_ch, unsigned int rate);
+int tabla_close_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+ unsigned int tot_ch);
+int tabla_close_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+ unsigned int tot_ch);
+int tabla_get_channel(struct tabla *tabla,
+ unsigned int *rx_ch,
+ unsigned int *tx_ch);
+#endif /* __WCD9310_SLIMSLAVE_H_ */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 427465d..07d5af65 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -1,6 +1,7 @@
/* include/linux/msm_mdp.h
*
* Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2012 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
@@ -77,6 +78,7 @@
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_Y_CBCR_H2V2_ADRENO,
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 */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 2cbe6ce..037cfe7 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -164,6 +164,7 @@
* @enable_dcd: Enable Data Contact Detection circuit. if not set
* wait for 600msec before proceeding to primary
* detection.
+ * @bus_scale_table: parameters for bus bandwidth requirements
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -179,6 +180,7 @@
bool disable_reset_on_disconnect;
u32 swfi_latency;
bool enable_dcd;
+ struct msm_bus_scale_pdata *bus_scale_table;
};
/**
@@ -211,6 +213,7 @@
collapse when cable is connected.
* @id_timer: The timer used for polling ID line to detect ACA states.
* @xo_handle: TCXO buffer handle
+ * @bus_perf_client: Bus performance client handle to request BUS bandwidth
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -241,6 +244,7 @@
struct timer_list id_timer;
unsigned long caps;
struct clk *xo_handle;
+ uint32_t bus_perf_client;
/*
* Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
* analog regulators while going to low power mode.
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index c97c664..9759b32 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@
enum wcnss_opcode opcode);
int req_riva_power_on_lock(char *driver_name);
int free_riva_power_on_lock(char *driver_name);
+unsigned int wcnss_get_serial_number(void);
#define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
#define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 8d2852b..87fbbd2 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -217,7 +217,8 @@
#define PP_SNAP 0x01
#define PP_RAW_SNAP ((0x01)<<1)
#define PP_PREV ((0x01)<<2)
-#define PP_MASK (PP_SNAP|PP_RAW_SNAP|PP_PREV)
+#define PP_THUMB ((0x01)<<3)
+#define PP_MASK (PP_SNAP|PP_RAW_SNAP|PP_PREV|PP_THUMB)
#define MSM_CAM_CTRL_CMD_DONE 0
#define MSM_CAM_SENSOR_VFE_CMD 1
@@ -295,6 +296,7 @@
struct msm_pp_frame_sp sp;
struct msm_pp_frame_mp mp[MAX_PLANES];
};
+ int node_type;
};
struct msm_cam_evt_divert_frame {
@@ -509,6 +511,9 @@
uint32_t window_height_lastline;
};
+#define VIDEO_NODE 0
+#define MCTL_NODE 1
+
#define OUTPUT_1 0
#define OUTPUT_2 1
#define OUTPUT_1_AND_2 2 /* snapshot only */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 7caafb6..5dd1445 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -58,6 +58,7 @@
#define MSG_ID_STATS_AWB_AEC 39
#define MSG_ID_OUTPUT_PRIMARY 40
#define MSG_ID_OUTPUT_SECONDARY 41
+#define MSG_ID_STATS_COMPOSITE 42
/* ISP command IDs */
#define VFE_CMD_DUMMY_0 0
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 30f1a7c..097ba39 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -234,10 +234,18 @@
/* HDMI_5Point1 (6-ch) = 2 */
/* HDMI_6Point1 (8-ch) = 3 */
u16 data_type; /* HDMI_Linear = 0 */
- /* HDMI_non_Linaer = 1 */
+ /* HDMI_non_Linear = 1 */
} __attribute__ ((packed));
+struct afe_port_hdmi_multi_ch_cfg {
+ u16 data_type; /* HDMI_Linear = 0 */
+ /* HDMI_non_Linear = 1 */
+ u16 channel_allocation; /* The default is 0 (Stereo) */
+ u16 reserved; /* must be set to 0 */
+} __packed;
+
+
/* Slimbus Device Ids */
#define AFE_SLIMBUS_DEVICE_1 0x0
#define AFE_SLIMBUS_DEVICE_2 0x1
@@ -264,6 +272,16 @@
u16 reserved;
} __packed;
+struct afe_port_slimbus_sch_cfg {
+ u16 slimbus_dev_id; /* SLIMBUS Device id.*/
+ u16 bit_width; /** bit width of the samples, 16, 24.*/
+ u16 data_format; /** data format.*/
+ u16 num_channels; /** Number of channels.*/
+ u16 reserved;
+ /** Slave channel mapping for respective channels.*/
+ u8 slave_ch_mapping[8];
+} __packed;
+
struct afe_port_rtproxy_cfg {
u16 bitwidth; /* 16,24,32 */
u16 interleaved; /* interleaved = 1 */
@@ -277,13 +295,17 @@
} __packed;
#define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
+#define AFE_PORT_AUDIO_SLIM_SCH_CONFIG 0x000100e4
+#define AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG 0x000100D9
union afe_port_config {
- struct afe_port_pcm_cfg pcm;
- struct afe_port_mi2s_cfg mi2s;
- struct afe_port_hdmi_cfg hdmi;
- struct afe_port_slimbus_cfg slimbus;
- struct afe_port_rtproxy_cfg rtproxy;
+ struct afe_port_pcm_cfg pcm;
+ struct afe_port_mi2s_cfg mi2s;
+ struct afe_port_hdmi_cfg hdmi;
+ struct afe_port_hdmi_multi_ch_cfg hdmi_multi_ch;
+ struct afe_port_slimbus_cfg slimbus;
+ struct afe_port_slimbus_sch_cfg slim_sch;
+ struct afe_port_rtproxy_cfg rtproxy;
} __attribute__((packed));
struct afe_audioif_config_command {
@@ -482,6 +504,20 @@
#define ADM_CMD_COPP_CLOSE 0x00010305
+#define ADM_CMD_MULTI_CHANNEL_COPP_OPEN 0x00010310
+struct adm_multi_ch_copp_open_command {
+ struct apr_hdr hdr;
+ u16 flags;
+ u16 mode; /* 1-RX, 2-Live TX, 3-Non Live TX */
+ u16 endpoint_id1;
+ u16 endpoint_id2;
+ u32 topology_id;
+ u16 channel_config;
+ u16 reserved;
+ u32 rate;
+ u8 dev_channel_mapping[8];
+} __packed;
+
#define ADM_CMD_MEMORY_MAP 0x00010C30
struct adm_cmd_memory_map{
struct apr_hdr hdr;
@@ -635,6 +671,9 @@
u16 reserved;
} __attribute__ ((packed));
+#define ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN 0x00010311
+
+
#define ASM_STREAM_PRIORITY_NORMAL 0
#define ASM_STREAM_PRIORITY_LOW 1
#define ASM_STREAM_PRIORITY_HIGH 2
@@ -676,6 +715,125 @@
u16 interleaved;
};
+#define PCM_CHANNEL_NULL 0
+
+/* Front left channel. */
+#define PCM_CHANNEL_FL 1
+
+/* Front right channel. */
+#define PCM_CHANNEL_FR 2
+
+/* Front center channel. */
+#define PCM_CHANNEL_FC 3
+
+/* Left surround channel.*/
+#define PCM_CHANNEL_LS 4
+
+/* Right surround channel.*/
+#define PCM_CHANNEL_RS 5
+
+/* Low frequency effect channel. */
+#define PCM_CHANNEL_LFE 6
+
+/* Center surround channel; Rear center channel. */
+#define PCM_CHANNEL_CS 7
+
+/* Left back channel; Rear left channel. */
+#define PCM_CHANNEL_LB 8
+
+/* Right back channel; Rear right channel. */
+#define PCM_CHANNEL_RB 9
+
+/* Top surround channel. */
+#define PCM_CHANNEL_TS 10
+
+/* Center vertical height channel.*/
+#define PCM_CHANNEL_CVH 11
+
+/* Mono surround channel.*/
+#define PCM_CHANNEL_MS 12
+
+/* Front left of center. */
+#define PCM_CHANNEL_FLC 13
+
+/* Front right of center. */
+#define PCM_CHANNEL_FRC 14
+
+/* Rear left of center. */
+#define PCM_CHANNEL_RLC 15
+
+/* Rear right of center. */
+#define PCM_CHANNEL_RRC 16
+
+#define PCM_FORMAT_MAX_NUM_CHANNEL 8
+
+
+/*
+ * Multiple-channel PCM decoder format block structure used in the
+ * #ASM_STREAM_CMD_OPEN_WRITE command.
+ * The data must be in little-endian format.
+ */
+struct asm_multi_channel_pcm_fmt_blk {
+
+ u16 num_channels; /*
+ * Number of channels.
+ * Supported values:1 to 8
+ */
+
+ u16 bits_per_sample; /*
+ * Number of bits per sample per channel.
+ * Supported values: 16, 24 When used for
+ * playback, the client must send 24-bit
+ * samples packed in 32-bit words. The
+ * 24-bit samples must be placed in the most
+ * significant 24 bits of the 32-bit word. When
+ * used for recording, the aDSP sends 24-bit
+ * samples packed in 32-bit words. The 24-bit
+ * samples are placed in the most significant
+ * 24 bits of the 32-bit word.
+ */
+
+ u32 sample_rate; /*
+ * Number of samples per second
+ * (in Hertz). Supported values:
+ * 2000 to 48000
+ */
+
+ u16 is_signed; /*
+ * Flag that indicates the samples
+ * are signed (1).
+ */
+
+ u16 is_interleaved; /*
+ * Flag that indicates whether the channels are
+ * de-interleaved (0) or interleaved (1).
+ * Interleaved format means corresponding
+ * samples from the left and right channels are
+ * interleaved within the buffer.
+ * De-interleaved format means samples from
+ * each channel are contiguous in the buffer.
+ * The samples from one channel immediately
+ * follow those of the previous channel.
+ */
+
+ u8 channel_mapping[8]; /*
+ * Supported values:
+ * PCM_CHANNEL_NULL, PCM_CHANNEL_FL,
+ * PCM_CHANNEL_FR, PCM_CHANNEL_FC,
+ * PCM_CHANNEL_LS, PCM_CHANNEL_RS,
+ * PCM_CHANNEL_LFE, PCM_CHANNEL_CS,
+ * PCM_CHANNEL_LB, PCM_CHANNEL_RB,
+ * PCM_CHANNEL_TS, PCM_CHANNEL_CVH,
+ * PCM_CHANNEL_MS, PCM_CHANNEL_FLC,
+ * PCM_CHANNEL_FRC, PCM_CHANNEL_RLC,
+ * PCM_CHANNEL_RRC.
+ * Channel[i] mapping describes channel I. Each
+ * element i of the array describes channel I
+ * inside the buffer where I < num_channels.
+ * An unused channel is set to zero.
+ */
+};
+
struct asm_adpcm_cfg {
u16 ch_cfg;
u16 bits_per_sample;
@@ -878,6 +1036,7 @@
#define MPEG4_MULTI_AAC 0x00010D86
#define US_POINT_EPOS_FORMAT 0x00012310
#define US_RAW_FORMAT 0x0001127C
+#define MULTI_CHANNEL_PCM 0x00010C66
#define ASM_ENCDEC_SBCRATE 0x00010C13
#define ASM_ENCDEC_IMMDIATE_DECODE 0x00010C14
@@ -1059,6 +1218,7 @@
struct asm_aac_cfg aac_cfg;
struct asm_flac_cfg flac_cfg;
struct asm_vorbis_cfg vorbis_cfg;
+ struct asm_multi_channel_pcm_fmt_blk multi_ch_pcm_cfg;
} __attribute__((packed)) write_cfg;
} __attribute__((packed));
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index 80374c5..fe25d22 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,9 @@
int adm_open(int port, int path, int rate, int mode, int topology);
+int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
+ int topology);
+
int adm_memory_map_regions(uint32_t *buf_add, uint32_t mempool_id,
uint32_t *bufsz, uint32_t bufcnt);
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 16439e8..d08f528 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,7 @@
#define FORMAT_WMA_V9 0x000f
#define FORMAT_AMR_WB_PLUS 0x0010
#define FORMAT_MPEG4_MULTI_AAC 0x0011
+#define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -244,6 +245,9 @@
int q6asm_media_format_block_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels);
+int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
+ uint32_t rate, uint32_t channels);
+
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index bda171e..f1ce01f 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -2,6 +2,7 @@
* linux/sound/soc-dai.h -- ALSA SoC Layer
*
* Copyright: 2005-2008 Wolfson Microelectronics. PLC.
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -121,6 +122,10 @@
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot);
+int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot);
+
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
/* Digital Audio Interface mute */
@@ -150,6 +155,9 @@
unsigned int rx_num, unsigned int *rx_slot);
int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
+ int (*get_channel_map)(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot);
/*
* DAI digital mute - optional.
* Called by soc-core to minimise any pops.
diff --git a/kernel/printk.c b/kernel/printk.c
index dbaa948..3c31395 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,7 +41,7 @@
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/rculist.h>
-
+#include <mach/msm_rtb.h>
#include <asm/uaccess.h>
/*
@@ -784,6 +784,11 @@
{
va_list args;
int r;
+#ifdef CONFIG_MSM_RTB
+ void *caller = __builtin_return_address(0);
+
+ uncached_logk_pc(LOGK_LOGBUF, caller, (void *)log_end);
+#endif
#ifdef CONFIG_KGDB_KDB
if (unlikely(kdb_trap_printk)) {
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e56fe35..b3b122f 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -686,6 +686,14 @@
bdi_unregister(bdi);
+ /*
+ * If bdi_unregister() had already been called earlier, the
+ * wakeup_timer could still be armed because bdi_prune_sb()
+ * can race with the bdi_wakeup_thread_delayed() calls from
+ * __mark_inode_dirty().
+ */
+ del_timer_sync(&bdi->wb.wakeup_timer);
+
for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
percpu_counter_destroy(&bdi->bdi_stat[i]);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index f0f2ac1..899c538 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -65,7 +65,7 @@
cp.peer_addr_type = conn->dst_type;
cp.conn_interval_min = cpu_to_le16(0x0008);
cp.conn_interval_max = cpu_to_le16(0x0100);
- cp.supervision_timeout = cpu_to_le16(0x0064);
+ cp.supervision_timeout = cpu_to_le16(1000);
cp.min_ce_len = cpu_to_le16(0x0001);
cp.max_ce_len = cpu_to_le16(0x0001);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ded74dc..b4dde4c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -7440,11 +7440,12 @@
BT_DBG("sk->scid %d", l2cap_pi(sk)->scid);
if (l2cap_pi(sk)->scid == L2CAP_CID_LE_DATA) {
- if (!status && encrypt)
+ if (!status && encrypt) {
l2cap_pi(sk)->sec_level = hcon->sec_level;
+ l2cap_chan_ready(sk);
+ }
del_timer(&hcon->smp_timer);
- l2cap_chan_ready(sk);
smp_link_encrypt_cmplt(conn, status, encrypt);
bh_unlock_sock(sk);
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 65744e1..0104f1a 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -57,8 +57,34 @@
"inode.c:74",
"msm_sdcc.c:126",
"msm_sdcc.c:128",
+ "nf_conntrack_core.c:1579",
+ "nf_conntrack_core.c:1580",
"nf_conntrack_netlink.c:790",
+ "nf_conntrack_proto.c:210",
+ "nf_conntrack_proto.c:345",
+ "nf_conntrack_proto.c:370",
+ "nf_nat_core.c:528",
+ "nf_nat_core.c:739",
+ "nf_nat_core.c:740",
+ "nf_nat_core.c:741",
+ "nf_nat_core.c:742",
+ "nf_nat_core.c:751",
+ "nf_nat_core.c:753",
+ "nf_nat_core.c:756",
+ "nf_nat_ftp.c:123",
+ "nf_nat_pptp.c:285",
+ "nf_nat_pptp.c:288",
+ "nf_nat_pptp.c:291",
+ "nf_nat_pptp.c:294",
+ "nf_nat_sip.c:550",
+ "nf_nat_sip.c:551",
+ "nf_nat_sip.c:552",
+ "nf_nat_sip.c:553",
+ "nf_nat_sip.c:555",
+ "nf_nat_sip.c:556",
+ "nf_nat_sip.c:554",
"nf_nat_standalone.c:118",
+ "nf_nat_tftp.c:46",
"return_address.c:62",
"sch_generic.c:678",
"soc-core.c:1719",
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d4e9ecf..deb13dc 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -36,8 +36,6 @@
#define NUM_DECIMATORS 10
#define NUM_INTERPOLATORS 7
#define BITS_PER_REG 8
-#define TABLA_RX_DAI_ID 1
-#define TABLA_TX_DAI_ID 2
#define TABLA_CFILT_FAST_MODE 0x00
#define TABLA_CFILT_SLOW_MODE 0x40
#define MBHC_FW_READ_ATTEMPTS 15
@@ -49,6 +47,17 @@
#define TABLA_OCP_ATTEMPT 1
+#define AIF1_PB 1
+#define AIF1_CAP 2
+#define NUM_CODEC_DAIS 2
+
+struct tabla_codec_dai_data {
+ u32 rate;
+ u32 *ch_num;
+ u32 ch_act;
+ u32 ch_tot;
+};
+
#define TABLA_MCLK_RATE_12288KHZ 12288000
#define TABLA_MCLK_RATE_9600KHZ 9600000
@@ -58,6 +67,7 @@
static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver tabla_dai[];
enum tabla_bandgap_type {
TABLA_BANDGAP_OFF = 0,
@@ -185,11 +195,6 @@
struct work_struct hphlocp_work; /* reporting left hph ocp off */
struct work_struct hphrocp_work; /* reporting right hph ocp off */
- /* pm_cnt holds number of sleep lock holders + 1
- * so if pm_cnt is 1 system is sleep-able. */
- atomic_t pm_cnt;
- wait_queue_head_t pm_wq;
-
u8 hphlocp_cnt; /* headphone left ocp retry */
u8 hphrocp_cnt; /* headphone right ocp retry */
@@ -199,6 +204,9 @@
/* Work to perform MBHC Firmware Read */
struct delayed_work mbhc_firmware_dwork;
const struct firmware *mbhc_fw;
+
+ /* num of slim ports required */
+ struct tabla_codec_dai_data dai[NUM_CODEC_DAIS];
};
#ifdef CONFIG_DEBUG_FS
@@ -1912,306 +1920,6 @@
return 0;
}
-static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
- /*RX stuff */
- SND_SOC_DAPM_OUTPUT("EAR"),
-
- SND_SOC_DAPM_PGA("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0),
-
- SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
- ARRAY_SIZE(dac1_switch)),
-
- SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-
- /* Headphone */
- SND_SOC_DAPM_OUTPUT("HEADPHONE"),
- SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
- tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
- hphl_switch, ARRAY_SIZE(hphl_switch)),
-
- SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
- tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
- tabla_hphr_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
- /* Speaker */
- SND_SOC_DAPM_OUTPUT("LINEOUT1"),
- SND_SOC_DAPM_OUTPUT("LINEOUT2"),
- SND_SOC_DAPM_OUTPUT("LINEOUT3"),
- SND_SOC_DAPM_OUTPUT("LINEOUT4"),
- SND_SOC_DAPM_OUTPUT("LINEOUT5"),
-
- SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL,
- 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL,
- 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL,
- 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL,
- 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA_E("LINEOUT5 PA", TABLA_A_RX_LINE_CNP_EN, 4, 0, NULL, 0,
- tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
- , tabla_lineout_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
- , tabla_lineout_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
- , tabla_lineout_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
- &lineout3_ground_switch),
- SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
- , tabla_lineout_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
- &lineout4_ground_switch),
- SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
- , tabla_lineout_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
- 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
-
-
- SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
- &rx4_dsm_mux, tabla_codec_reset_interpolator,
- SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
- &rx6_dsm_mux, tabla_codec_reset_interpolator,
- SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
- SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
-
- SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx2_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx2_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx3_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx3_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx4_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx4_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx5_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx5_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx6_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx6_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx7_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx7_mix1_inp2_mux),
-
- SND_SOC_DAPM_SUPPLY("CP", TABLA_A_CP_EN, 0, 0,
- tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD),
-
- SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
- tabla_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- /* TX */
-
- SND_SOC_DAPM_SUPPLY("CDC_CONN", TABLA_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
- 0),
-
- SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0,
- tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_INPUT("AMIC1"),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TABLA_A_MICB_1_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TABLA_A_MICB_1_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
- tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_INPUT("AMIC3"),
- SND_SOC_DAPM_ADC_E("ADC3", NULL, TABLA_A_TX_3_4_EN, 7, 0,
- tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_INPUT("AMIC4"),
- SND_SOC_DAPM_ADC_E("ADC4", NULL, TABLA_A_TX_3_4_EN, 3, 0,
- tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_INPUT("AMIC5"),
- SND_SOC_DAPM_ADC_E("ADC5", NULL, TABLA_A_TX_5_6_EN, 7, 0,
- tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_INPUT("AMIC6"),
- SND_SOC_DAPM_ADC_E("ADC6", NULL, TABLA_A_TX_5_6_EN, 3, 0,
- tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
- &dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
- &dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
- &dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
- &dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
- &dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
- &dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
- &dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
- &dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
- &dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
- &dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-
- SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
- SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
-
- SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
- tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
-
- SND_SOC_DAPM_INPUT("AMIC2"),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TABLA_A_MICB_2_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TABLA_A_MICB_2_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TABLA_A_MICB_2_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TABLA_A_MICB_3_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TABLA_A_MICB_3_CTL, 7, 0,
- tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
- tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
- SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 0, 0),
-
- SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
- SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 4, 0),
-
- SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
- SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 5, 0),
-
- SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
- SND_SOC_DAPM_AIF_OUT("SLIM TX7", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 0, 0),
-
- SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
- SND_SOC_DAPM_AIF_OUT("SLIM TX8", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 0, 0),
-
- SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
- SND_SOC_DAPM_AIF_OUT("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 0, 0),
-
- SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
- SND_SOC_DAPM_AIF_OUT("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 0, 0),
-
- /* Digital Mic Inputs */
- SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
- tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
- tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
- tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
- tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
- tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
- tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- /* Sidetone */
- SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
- SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
-};
-
static const struct snd_soc_dapm_widget tabla_1_x_dapm_widgets[] = {
SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_1_A_MICB_4_CTL, 7,
0, tabla_codec_enable_micbias,
@@ -2680,7 +2388,6 @@
{
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
- pr_debug("%s: enable = %d\n", __func__, enable);
if (enable) {
snd_soc_update_bits(codec, TABLA_A_CONFIG_MODE_FREQ, 0x10, 0);
snd_soc_write(codec, TABLA_A_BIAS_CONFIG_MODE_BG_CTL, 0x17);
@@ -2885,11 +2592,11 @@
case SND_SOC_DAIFMT_CBS_CFS:
/* CPU is master */
if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
- if (dai->id == TABLA_TX_DAI_ID)
+ if (dai->id == AIF1_CAP)
snd_soc_update_bits(dai->codec,
TABLA_A_CDC_CLK_TX_I2S_CTL,
TABLA_I2S_MASTER_MODE_MASK, 0);
- else if (dai->id == TABLA_RX_DAI_ID)
+ else if (dai->id == AIF1_PB)
snd_soc_update_bits(dai->codec,
TABLA_A_CDC_CLK_RX_I2S_CTL,
TABLA_I2S_MASTER_MODE_MASK, 0);
@@ -2899,10 +2606,10 @@
/* CPU is slave */
if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
val = TABLA_I2S_MASTER_MODE_MASK;
- if (dai->id == TABLA_TX_DAI_ID)
+ if (dai->id == AIF1_CAP)
snd_soc_update_bits(dai->codec,
TABLA_A_CDC_CLK_TX_I2S_CTL, val, val);
- else if (dai->id == TABLA_RX_DAI_ID)
+ else if (dai->id == AIF1_PB)
snd_soc_update_bits(dai->codec,
TABLA_A_CDC_CLK_RX_I2S_CTL, val, val);
}
@@ -2913,6 +2620,71 @@
return 0;
}
+static int tabla_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
+ u32 i = 0;
+ if (!tx_slot && !rx_slot) {
+ pr_err("%s: Invalid\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: DAI-ID %x %d %d\n", __func__, dai->id, tx_num, rx_num);
+
+ if (dai->id == AIF1_PB) {
+ for (i = 0; i < rx_num; i++) {
+ tabla->dai[dai->id - 1].ch_num[i] = rx_slot[i];
+ tabla->dai[dai->id - 1].ch_act = 0;
+ tabla->dai[dai->id - 1].ch_tot = rx_num;
+ }
+ } else if (dai->id == AIF1_CAP) {
+ for (i = 0; i < tx_num; i++) {
+ tabla->dai[dai->id - 1].ch_num[i] = tx_slot[i];
+ tabla->dai[dai->id - 1].ch_act = 0;
+ tabla->dai[dai->id - 1].ch_tot = tx_num;
+ }
+ }
+ return 0;
+}
+
+static int tabla_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+ struct tabla *tabla = dev_get_drvdata(dai->codec->control_data);
+
+ u32 cnt = 0;
+ u32 tx_ch[SLIM_MAX_TX_PORTS];
+ u32 rx_ch[SLIM_MAX_RX_PORTS];
+
+ if (!rx_slot && !tx_slot) {
+ pr_err("%s: Invalid\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
+ /* for virtual port, codec driver needs to do
+ * housekeeping, for now should be ok
+ */
+ tabla_get_channel(tabla, rx_ch, tx_ch);
+ if (dai->id == AIF1_PB) {
+ *rx_num = tabla_dai[dai->id - 1].playback.channels_max;
+ while (cnt < *rx_num) {
+ rx_slot[cnt] = rx_ch[cnt];
+ cnt++;
+ }
+ } else if (dai->id == AIF1_CAP) {
+ *tx_num = tabla_dai[dai->id - 1].capture.channels_max;
+ while (cnt < *tx_num) {
+ tx_slot[cnt] = tx_ch[6 + cnt];
+ cnt++;
+ }
+ }
+ return 0;
+}
+
static int tabla_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -2923,7 +2695,8 @@
u16 tx_fs_reg, rx_fs_reg;
u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
- pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
+ pr_debug("%s: DAI-ID %x rate %d\n", __func__, dai->id,
+ params_rate(params));
switch (params_rate(params)) {
case 8000:
@@ -2953,7 +2726,7 @@
* If current dai is a tx dai, set sample rate to
* all the txfe paths that are currently not active
*/
- if (dai->id == TABLA_TX_DAI_ID) {
+ if (dai->id == AIF1_CAP) {
tx_state = snd_soc_read(codec,
TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL);
@@ -2992,9 +2765,10 @@
}
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_TX_I2S_CTL,
0x03, tx_fs_rate);
+ } else {
+ tabla->dai[dai->id - 1].rate = params_rate(params);
}
}
-
/**
* TODO: Need to handle case where same RX chain takes 2 or more inputs
* with varying sample rates
@@ -3004,7 +2778,7 @@
* If current dai is a rx dai, set sample rate to
* all the rx paths that are currently not active
*/
- if (dai->id == TABLA_RX_DAI_ID) {
+ if (dai->id == AIF1_PB) {
rx_state = snd_soc_read(codec,
TABLA_A_CDC_CLK_RX_B1_CTL);
@@ -3037,6 +2811,8 @@
}
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_I2S_CTL,
0x03, (rx_fs_rate >> 0x05));
+ } else {
+ tabla->dai[dai->id - 1].rate = params_rate(params);
}
}
@@ -3049,12 +2825,14 @@
.hw_params = tabla_hw_params,
.set_sysclk = tabla_set_dai_sysclk,
.set_fmt = tabla_set_dai_fmt,
+ .set_channel_map = tabla_set_channel_map,
+ .get_channel_map = tabla_get_channel_map,
};
static struct snd_soc_dai_driver tabla_dai[] = {
{
.name = "tabla_rx1",
- .id = 1,
+ .id = AIF1_PB,
.playback = {
.stream_name = "AIF1 Playback",
.rates = WCD9310_RATES,
@@ -3062,13 +2840,13 @@
.rate_max = 48000,
.rate_min = 8000,
.channels_min = 1,
- .channels_max = 4,
+ .channels_max = 2,
},
.ops = &tabla_dai_ops,
},
{
.name = "tabla_tx1",
- .id = 2,
+ .id = AIF1_CAP,
.capture = {
.stream_name = "AIF1 Capture",
.rates = WCD9310_RATES,
@@ -3076,7 +2854,7 @@
.rate_max = 48000,
.rate_min = 8000,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 4,
},
.ops = &tabla_dai_ops,
},
@@ -3112,6 +2890,426 @@
.ops = &tabla_dai_ops,
},
};
+
+static int tabla_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct tabla *tabla;
+ struct snd_soc_codec *codec = w->codec;
+ struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
+ u32 j = 0;
+ u32 ret = 0;
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ tabla = codec->control_data;
+ /* Execute the callback only if interface type is slimbus */
+ if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+ return 0;
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+ if (tabla_dai[j].id == AIF1_CAP)
+ continue;
+ if (!strncmp(w->sname,
+ tabla_dai[j].playback.stream_name, 13)) {
+ ++tabla_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
+ ret = tabla_cfg_slim_sch_rx(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot,
+ tabla_p->dai[j].rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+ if (tabla_dai[j].id == AIF1_CAP)
+ continue;
+ if (!strncmp(w->sname,
+ tabla_dai[j].playback.stream_name, 13)) {
+ --tabla_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (!tabla_p->dai[j].ch_act) {
+ ret = tabla_close_slim_sch_rx(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot);
+ tabla_p->dai[j].rate = 0;
+ memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
+ tabla_p->dai[j].ch_tot));
+ tabla_p->dai[j].ch_tot = 0;
+ }
+ }
+ return ret;
+}
+
+static int tabla_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct tabla *tabla;
+ struct snd_soc_codec *codec = w->codec;
+ struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
+ /* index to the DAI ID, for now hardcoding */
+ u32 j = 0;
+ u32 ret = 0;
+
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ tabla = codec->control_data;
+
+ /* Execute the callback only if interface type is slimbus */
+ if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+ return 0;
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+ if (tabla_dai[j].id == AIF1_PB)
+ continue;
+ if (!strncmp(w->sname,
+ tabla_dai[j].capture.stream_name, 13)) {
+ ++tabla_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
+ ret = tabla_cfg_slim_sch_tx(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot,
+ tabla_p->dai[j].rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
+ if (tabla_dai[j].id == AIF1_PB)
+ continue;
+ if (!strncmp(w->sname,
+ tabla_dai[j].capture.stream_name, 13)) {
+ --tabla_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (!tabla_p->dai[j].ch_act) {
+ ret = tabla_close_slim_sch_tx(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot);
+ tabla_p->dai[j].rate = 0;
+ memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
+ tabla_p->dai[j].ch_tot));
+ tabla_p->dai[j].ch_tot = 0;
+ }
+ }
+ return ret;
+}
+
+/* Todo: Have seperate dapm widgets for I2S and Slimbus.
+ * Might Need to have callbacks registered only for slimbus
+ */
+static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
+ /*RX stuff */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+
+ SND_SOC_DAPM_PGA("EAR PA", TABLA_A_RX_EAR_EN, 4, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
+ ARRAY_SIZE(dac1_switch)),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Headphone */
+ SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+ tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("HPHL DAC", TABLA_A_RX_HPH_L_DAC_CTL, 7, 0,
+ hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+ SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+ tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
+ tabla_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Speaker */
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT3"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT4"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT5"),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL,
+ 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL,
+ 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL,
+ 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL,
+ 0, tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT5 PA", TABLA_A_RX_LINE_CNP_EN, 4, 0, NULL, 0,
+ tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
+ &lineout3_ground_switch),
+ SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
+ &lineout4_ground_switch),
+ SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX2 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
+ 0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
+ &rx4_dsm_mux, tabla_codec_reset_interpolator,
+ SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
+ &rx6_dsm_mux, tabla_codec_reset_interpolator,
+ SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx5_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx5_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx6_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx6_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx7_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx7_mix1_inp2_mux),
+
+ SND_SOC_DAPM_SUPPLY("CP", TABLA_A_CP_EN, 0, 0,
+ tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
+ tabla_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* TX */
+
+ SND_SOC_DAPM_SUPPLY("CDC_CONN", TABLA_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+ 0),
+
+ SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0,
+ tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TABLA_A_MICB_1_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TABLA_A_MICB_1_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TABLA_A_MICB_1_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, TABLA_A_TX_1_2_EN, 7, 0,
+ tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC3"),
+ SND_SOC_DAPM_ADC_E("ADC3", NULL, TABLA_A_TX_3_4_EN, 7, 0,
+ tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC4"),
+ SND_SOC_DAPM_ADC_E("ADC4", NULL, TABLA_A_TX_3_4_EN, 3, 0,
+ tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC5"),
+ SND_SOC_DAPM_ADC_E("ADC5", NULL, TABLA_A_TX_5_6_EN, 7, 0,
+ tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_INPUT("AMIC6"),
+ SND_SOC_DAPM_ADC_E("ADC6", NULL, TABLA_A_TX_5_6_EN, 3, 0,
+ tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+ &dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+ &dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+ &dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+ &dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
+ &dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
+ &dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
+ &dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
+ &dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
+ &dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
+ &dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+ SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
+ SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
+ tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
+
+ SND_SOC_DAPM_INPUT("AMIC2"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TABLA_A_MICB_2_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TABLA_A_MICB_2_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TABLA_A_MICB_2_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TABLA_A_MICB_2_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TABLA_A_MICB_3_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TABLA_A_MICB_3_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TABLA_A_MICB_3_CTL, 7, 0,
+ tabla_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2", NULL, TABLA_A_TX_1_2_EN, 3, 0,
+ tabla_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
+ SND_SOC_DAPM_AIF_OUT("SLIM TX1", "AIF1 Capture", NULL, SND_SOC_NOPM,
+ 0, 0),
+
+ SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
+ SND_SOC_DAPM_AIF_OUT("SLIM TX5", "AIF1 Capture", NULL, SND_SOC_NOPM,
+ 4, 0),
+
+ SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
+ SND_SOC_DAPM_AIF_OUT("SLIM TX6", "AIF1 Capture", NULL, SND_SOC_NOPM,
+ 5, 0),
+
+ SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX7", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX8", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
+ 0, 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
+ 0, 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+ tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+ tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+ tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+ tabla_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Sidetone */
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_PGA("IIR1", TABLA_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+};
+
static short tabla_codec_read_sta_result(struct snd_soc_codec *codec)
{
u8 bias_msb, bias_lsb;
@@ -3331,24 +3529,6 @@
return 0;
}
-static void tabla_lock_sleep(struct tabla_priv *tabla)
-{
- int ret;
- while (!(ret = wait_event_timeout(tabla->pm_wq,
- atomic_inc_not_zero(&tabla->pm_cnt),
- 2 * HZ))) {
- pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
- __func__, ret, atomic_read(&tabla->pm_cnt));
- WARN_ON_ONCE(1);
- }
-}
-
-static void tabla_unlock_sleep(struct tabla_priv *tabla)
-{
- atomic_dec(&tabla->pm_cnt);
- wake_up(&tabla->pm_wq);
-}
-
static u16 tabla_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
s16 vin_mv)
{
@@ -3403,11 +3583,13 @@
struct tabla_priv *tabla;
short bias_value;
int dce_mv, sta_mv;
+ struct tabla *core;
pr_debug("%s:\n", __func__);
delayed_work = to_delayed_work(work);
tabla = container_of(delayed_work, struct tabla_priv, btn0_dwork);
+ core = dev_get_drvdata(tabla->codec->dev->parent);
if (tabla) {
if (tabla->button_jack) {
@@ -3428,7 +3610,7 @@
pr_err("%s: Bad tabla private data\n", __func__);
}
- tabla_unlock_sleep(tabla);
+ tabla_unlock_sleep(core);
}
void tabla_mbhc_cal(struct snd_soc_codec *codec)
@@ -3877,10 +4059,10 @@
TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
short btnmeas[d->n_btn_meas + 1];
struct snd_soc_codec *codec = priv->codec;
+ struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
- tabla_lock_sleep(priv);
bias_value_dce = tabla_codec_read_dce_result(codec);
bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
@@ -3926,11 +4108,12 @@
/* XXX: assuming button 0 has the lowest micbias voltage */
if (btn == 0) {
+ tabla_lock_sleep(core);
if (schedule_delayed_work(&priv->btn0_dwork,
msecs_to_jiffies(400)) == 0) {
WARN(1, "Button pressed twice without release"
"event\n");
- tabla_unlock_sleep(priv);
+ tabla_unlock_sleep(core);
}
} else {
pr_debug("%s: Reporting short button %d(0x%x) press\n",
@@ -3938,23 +4121,24 @@
tabla_snd_soc_jack_report(priv, priv->button_jack, mask,
mask);
}
- } else
+ } else {
pr_debug("%s: bogus button press, too short press?\n",
__func__);
+ }
return IRQ_HANDLED;
}
static irqreturn_t tabla_release_handler(int irq, void *data)
{
- struct tabla_priv *priv = data;
- struct snd_soc_codec *codec = priv->codec;
int ret;
short mb_v;
+ struct tabla_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
pr_debug("%s: enter\n", __func__);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
- tabla_lock_sleep(priv);
if (priv->buttons_pressed & SND_JACK_BTN_0) {
ret = cancel_delayed_work(&priv->btn0_dwork);
@@ -3968,7 +4152,7 @@
} else {
/* if scheduled btn0_dwork is canceled from here,
* we have to unlock from here instead btn0_work */
- tabla_unlock_sleep(priv);
+ tabla_unlock_sleep(core);
mb_v = tabla_codec_sta_dce(codec, 0);
pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
__func__, mb_v,
@@ -4006,7 +4190,6 @@
}
tabla_codec_start_hs_polling(codec);
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4157,7 +4340,6 @@
pr_debug("%s: enter\n", __func__);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
- tabla_lock_sleep(priv);
is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
@@ -4229,7 +4411,6 @@
}
tabla_codec_shutdown_hs_removal_detect(codec);
tabla_codec_enable_hs_detect(codec, 1);
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4308,7 +4489,6 @@
tabla_sync_hph_state(priv);
}
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4326,7 +4506,6 @@
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
- tabla_lock_sleep(priv);
usleep_range(generic->t_shutdown_plug_rem,
generic->t_shutdown_plug_rem);
@@ -4364,7 +4543,6 @@
tabla_codec_enable_hs_detect(codec, 1);
}
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4377,8 +4555,6 @@
int i, j;
u8 val;
- tabla_lock_sleep(priv);
-
for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
slimbus_value = tabla_interface_reg_read(codec->control_data,
TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
@@ -4396,7 +4572,6 @@
TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
}
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4708,6 +4883,7 @@
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret = 0;
int i;
+ int ch_cnt;
codec->control_data = dev_get_drvdata(codec->dev->parent);
control = codec->control_data;
@@ -4742,8 +4918,6 @@
tabla->codec = codec;
tabla->pdata = dev_get_platdata(codec->dev->parent);
tabla->intf_type = tabla_get_intf_type();
- atomic_set(&tabla->pm_cnt, 1);
- init_waitqueue_head(&tabla->pm_wq);
tabla_update_reg_address(tabla);
tabla_update_reg_defaults(codec);
@@ -4861,6 +5035,20 @@
goto err_hphr_ocp_irq;
}
tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
+ for (i = 0; i < ARRAY_SIZE(tabla_dai); i++) {
+ switch (tabla_dai[i].id) {
+ case AIF1_PB:
+ ch_cnt = tabla_dai[i].playback.channels_max;
+ break;
+ case AIF1_CAP:
+ ch_cnt = tabla_dai[i].capture.channels_max;
+ break;
+ default:
+ continue;
+ }
+ tabla->dai[i].ch_num = kzalloc((sizeof(unsigned int)*
+ ch_cnt), GFP_KERNEL);
+ }
#ifdef CONFIG_DEBUG_FS
debug_tabla_priv = tabla;
@@ -4887,6 +5075,7 @@
}
static int tabla_codec_remove(struct snd_soc_codec *codec)
{
+ int i;
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
@@ -4897,6 +5086,8 @@
tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
if (tabla->mbhc_fw)
release_firmware(tabla->mbhc_fw);
+ for (i = 0; i < ARRAY_SIZE(tabla_dai); i++)
+ kfree(tabla->dai[i].ch_num);
kfree(tabla);
return 0;
}
@@ -4941,7 +5132,6 @@
buf = (char *)lbuf;
debug_tabla_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
? false : true;
-
return rc;
}
@@ -4954,53 +5144,14 @@
#ifdef CONFIG_PM
static int tabla_suspend(struct device *dev)
{
- int ret = 0, cnt;
- struct platform_device *pdev = to_platform_device(dev);
- struct tabla_priv *tabla = platform_get_drvdata(pdev);
-
- cnt = atomic_read(&tabla->pm_cnt);
- if (cnt > 0) {
- if (wait_event_timeout(tabla->pm_wq,
- (atomic_cmpxchg(&tabla->pm_cnt, 1, 0)
- == 1), 5 * HZ)) {
- dev_dbg(dev, "system suspend pm_cnt %d\n",
- atomic_read(&tabla->pm_cnt));
- } else {
- dev_err(dev, "%s timed out pm_cnt = %d\n",
- __func__, atomic_read(&tabla->pm_cnt));
- WARN_ON_ONCE(1);
- ret = -EBUSY;
- }
- } else if (cnt == 0)
- dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
- atomic_read(&tabla->pm_cnt));
- else {
- WARN(1, "unexpected pm_cnt %d\n", cnt);
- ret = -EFAULT;
- }
-
- return ret;
+ dev_dbg(dev, "%s: system suspend\n", __func__);
+ return 0;
}
static int tabla_resume(struct device *dev)
{
- int ret = 0, cnt;
- struct platform_device *pdev = to_platform_device(dev);
- struct tabla_priv *tabla = platform_get_drvdata(pdev);
-
- cnt = atomic_cmpxchg(&tabla->pm_cnt, 0, 1);
- if (cnt == 0) {
- dev_dbg(dev, "system resume, pm_cnt %d\n",
- atomic_read(&tabla->pm_cnt));
- wake_up_all(&tabla->pm_wq);
- } else if (cnt > 0)
- dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
- else {
- WARN(1, "unexpected pm_cnt %d\n", cnt);
- ret = -EFAULT;
- }
-
- return ret;
+ dev_dbg(dev, "%s: system resume\n", __func__);
+ return 0;
}
static const struct dev_pm_ops tabla_pm_ops = {
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 6ddc471..9c430b9 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -11,6 +11,7 @@
*/
#include <sound/soc.h>
#include <sound/jack.h>
+#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
#define TABLA_NUM_REGISTERS 0x400
#define TABLA_MAX_REGISTER (TABLA_NUM_REGISTERS-1)
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 9e0549b..1ed5f74 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -80,6 +80,13 @@
config SND_VOIP_PCM
tristate
+config SND_SOC_MSM_QDSP6_HDMI_AUDIO
+ tristate "Soc QDSP6 HDMI Audio DAI driver"
+ depends on FB_MSM_HDMI_MSM_PANEL
+ default n
+ help
+ To support HDMI Audio on MSM8960 over QDSP6.
+
config MSM_8x60_VOIP
tristate "SoC Machine driver for voip"
depends on SND_SOC_MSM8X60
@@ -120,6 +127,7 @@
select SND_SOC_MSM_STUB
select SND_SOC_WCD9310
select SND_SOC_MSM_HOSTLESS_PCM
+ select SND_SOC_MSM_QDSP6_HDMI_AUDIO
default n
help
To add support for SoC audio on MSM8960 and APQ8064 boards
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index c583ce2..1b3014e 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -56,7 +56,8 @@
obj-$(CONFIG_SND_SOC_MSM_QDSP6_INTF) += qdsp6/
-snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+obj-$(CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO) += msm-dai-q6-hdmi.o
obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index bd41e0b..b5150903 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -671,6 +671,66 @@
return tabla_cal;
}
+static int msm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+
+ pr_debug("%s: ch=%d\n", __func__,
+ msm_slim_0_rx_ch);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n", __func__);
+ goto end;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+ msm_slim_0_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+ msm_slim_0_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set codec channel map\n",
+ __func__);
+ goto end;
+ }
+ } else {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ msm_slim_0_tx_ch, tx_ch, 0 , 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(codec_dai,
+ msm_slim_0_tx_ch, tx_ch, 0, 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set codec channel map\n",
+ __func__);
+ goto end;
+ }
+
+
+ }
+end:
+ return ret;
+}
+
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int err;
@@ -924,6 +984,7 @@
static struct snd_soc_ops msm_be_ops = {
.startup = msm_startup,
+ .hw_params = msm_hw_params,
.shutdown = msm_shutdown,
};
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 42e7935..8f71e83 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -75,7 +75,7 @@
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 6,
.rate_min = 8000,
.rate_max = 48000,
},
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
new file mode 100644
index 0000000..6907ded
--- /dev/null
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -0,0 +1,283 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wcd9310/core.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/apr_audio.h>
+#include <sound/q6afe.h>
+#include <sound/q6adm.h>
+#include <sound/msm-dai-q6.h>
+#include <mach/clk.h>
+#include <mach/msm_hdmi_audio.h>
+
+
+enum {
+ STATUS_PORT_STARTED, /* track if AFE port has started */
+ STATUS_MAX
+};
+
+struct msm_dai_q6_hdmi_dai_data {
+ DECLARE_BITMAP(status_mask, STATUS_MAX);
+ u32 rate;
+ u32 channels;
+ union afe_port_config port_config;
+};
+
+
+/* Current implementation assumes hw_param is called once
+ * This may not be the case but what to do when ADM and AFE
+ * port are already opened and parameter changes
+ */
+static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ u32 channel_allocation = 0;
+ u32 level_shift = 0; /* 0dB */
+ bool down_mix = FALSE;
+
+ dai_data->channels = params_channels(params);
+ dai_data->rate = params_rate(params);
+ dai_data->port_config.hdmi_multi_ch.data_type = 0;
+ dai_data->port_config.hdmi_multi_ch.reserved = 0;
+
+ switch (dai_data->channels) {
+ case 2:
+ channel_allocation = 0;
+ hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_2,
+ channel_allocation, level_shift, down_mix);
+ dai_data->port_config.hdmi_multi_ch.channel_allocation =
+ channel_allocation;
+ break;
+ case 6:
+ channel_allocation = 0x0B;
+ hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_6,
+ channel_allocation, level_shift, down_mix);
+ dai_data->port_config.hdmi_multi_ch.channel_allocation =
+ channel_allocation;
+ break;
+ default:
+ dev_err(dai->dev, "invalid Channels = %u\n",
+ dai_data->channels);
+ return -EINVAL;
+ }
+ dev_dbg(dai->dev, "%s() num_ch = %u rate =%u"
+ " channel_allocation = %u\n", __func__, dai_data->channels,
+ dai_data->rate,
+ dai_data->port_config.hdmi_multi_ch.channel_allocation);
+
+ return 0;
+}
+
+
+static void msm_dai_q6_hdmi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ int rc = 0;
+
+ if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ pr_info("%s: afe port not started. dai_data->status_mask"
+ " = %ld\n", __func__, *dai_data->status_mask);
+ return;
+ }
+
+ rc = afe_close(dai->id); /* can block */
+
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to close AFE port\n");
+
+ pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
+ *dai_data->status_mask);
+
+ clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+}
+
+
+static int msm_dai_q6_hdmi_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ int rc = 0;
+
+ if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ /* PORT START should be set if prepare called in active state */
+ rc = afe_q6_interface_prepare();
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to open AFE APR\n");
+ }
+ return rc;
+}
+
+static int msm_dai_q6_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+ /* Start/stop port without waiting for Q6 AFE response. Need to have
+ * native q6 AFE driver propagates AFE response in order to handle
+ * port start/stop command error properly if error does arise.
+ */
+ pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
+ __func__, dai->id, cmd, *dai_data->status_mask);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ afe_port_start_nowait(dai->id, &dai_data->port_config,
+ dai_data->rate);
+
+ set_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ afe_port_stop_nowait(dai->id);
+ clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+ }
+ break;
+
+ default:
+ dev_err(dai->dev, "invalid Trigger command = %d\n", cmd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data;
+ int rc = 0;
+
+ dai_data = kzalloc(sizeof(struct msm_dai_q6_hdmi_dai_data),
+ GFP_KERNEL);
+
+ if (!dai_data) {
+ dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
+ dai->id);
+ rc = -ENOMEM;
+ } else
+ dev_set_drvdata(dai->dev, dai_data);
+
+ return rc;
+}
+
+static int msm_dai_q6_hdmi_dai_remove(struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data;
+ int rc;
+
+ dai_data = dev_get_drvdata(dai->dev);
+
+ /* If AFE port is still up, close it */
+ if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ rc = afe_close(dai->id); /* can block */
+
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to close AFE port\n");
+
+ clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+ }
+ kfree(dai_data);
+ snd_soc_unregister_dai(dai->dev);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops msm_dai_q6_hdmi_ops = {
+ .prepare = msm_dai_q6_hdmi_prepare,
+ .trigger = msm_dai_q6_hdmi_trigger,
+ .hw_params = msm_dai_q6_hdmi_hw_params,
+ .shutdown = msm_dai_q6_hdmi_shutdown,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 2,
+ .channels_max = 6,
+ .rate_max = 48000,
+ .rate_min = 48000,
+ },
+ .ops = &msm_dai_q6_hdmi_ops,
+ .probe = msm_dai_q6_hdmi_dai_probe,
+ .remove = msm_dai_q6_hdmi_dai_remove,
+};
+
+
+/* To do: change to register DAIs as batch */
+static __devinit int msm_dai_q6_hdmi_dev_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ dev_dbg(&pdev->dev, "dev name %s dev-id %d\n",
+ dev_name(&pdev->dev), pdev->id);
+
+ switch (pdev->id) {
+ case HDMI_RX:
+ rc = snd_soc_register_dai(&pdev->dev,
+ &msm_dai_q6_hdmi_hdmi_rx_dai);
+ break;
+ default:
+ dev_err(&pdev->dev, "invalid device ID %d\n", pdev->id);
+ rc = -ENODEV;
+ break;
+ }
+ return rc;
+}
+
+static __devexit int msm_dai_q6_hdmi_dev_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_dai(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver msm_dai_q6_hdmi_driver = {
+ .probe = msm_dai_q6_hdmi_dev_probe,
+ .remove = msm_dai_q6_hdmi_dev_remove,
+ .driver = {
+ .name = "msm-dai-q6-hdmi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_dai_q6_hdmi_init(void)
+{
+ return platform_driver_register(&msm_dai_q6_hdmi_driver);
+}
+module_init(msm_dai_q6_hdmi_init);
+
+static void __exit msm_dai_q6_hdmi_exit(void)
+{
+ platform_driver_unregister(&msm_dai_q6_hdmi_driver);
+}
+module_exit(msm_dai_q6_hdmi_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MSM DSP HDMI DAI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index c7d7004..aff87ae 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -206,110 +206,33 @@
return 0;
}
-static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
-
- dev_dbg(dai->dev, "%s start HDMI port\n", __func__);
-
- dai_data->channels = params_channels(params);
- switch (dai_data->channels) {
- case 2:
- dai_data->port_config.hdmi.channel_mode = 0; /* Put in macro */
- break;
- default:
- return -EINVAL;
- break;
- }
-
- /* Q6 only supports 16 as now */
- dai_data->port_config.hdmi.bitwidth = 16;
- dai_data->port_config.hdmi.data_type = 0;
- dai_data->rate = params_rate(params);
-
- return 0;
-}
static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai, int stream)
{
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
- u8 pgd_la, inf_la;
- u16 *slave_port_mapping;
-
- memset(dai_data->port_config.slimbus.slave_port_mapping, 0,
- sizeof(dai_data->port_config.slimbus.slave_port_mapping));
dai_data->channels = params_channels(params);
-
- slave_port_mapping = dai_data->port_config.slimbus.slave_port_mapping;
-
- switch (dai_data->channels) {
- case 4:
- if (dai->id == SLIMBUS_0_TX) {
- slave_port_mapping[0] = 7;
- slave_port_mapping[1] = 8;
- slave_port_mapping[2] = 9;
- slave_port_mapping[3] = 10;
- } else {
- return -EINVAL;
- }
- break;
- case 3:
- if (dai->id == SLIMBUS_0_TX) {
- slave_port_mapping[0] = 7;
- slave_port_mapping[1] = 8;
- slave_port_mapping[2] = 9;
- } else {
- return -EINVAL;
- }
- break;
- case 2:
- if (dai->id == SLIMBUS_0_RX) {
- slave_port_mapping[0] = 1;
- slave_port_mapping[1] = 2;
- } else {
- slave_port_mapping[0] = 7;
- slave_port_mapping[1] = 8;
- }
- break;
- case 1:
- if (dai->id == SLIMBUS_0_RX)
- slave_port_mapping[0] = 1;
- else
- slave_port_mapping[0] = 7;
- break;
- default:
- return -EINVAL;
- break;
- }
dai_data->rate = params_rate(params);
- tabla_get_logical_addresses(&pgd_la, &inf_la);
dai_data->port_config.slimbus.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1;
- dai_data->port_config.slimbus.slave_dev_pgd_la = pgd_la;
- dai_data->port_config.slimbus.slave_dev_intfdev_la = inf_la;
/* Q6 only supports 16 as now */
- dai_data->port_config.slimbus.bit_width = 16;
- dai_data->port_config.slimbus.data_format = 0;
- dai_data->port_config.slimbus.num_channels = dai_data->channels;
- dai_data->port_config.slimbus.reserved = 0;
+ dai_data->port_config.slim_sch.bit_width = 16;
+ dai_data->port_config.slim_sch.data_format = 0;
+ dai_data->port_config.slim_sch.num_channels = dai_data->channels;
+ dai_data->port_config.slim_sch.reserved = 0;
- dev_dbg(dai->dev, "slimbus_dev_id %hu slave_dev_pgd_la 0x%hx\n"
- "slave_dev_intfdev_la 0x%hx bit_width %hu data_format %hu\n"
- "num_channel %hu slave_port_mapping[0] %hu\n"
+ dev_dbg(dai->dev, "%s:slimbus_dev_id[%hu] bit_wd[%hu] format[%hu]\n"
+ "num_channel %hu slave_ch_mapping[0] %hu\n"
"slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
- "sample_rate %d\n",
- dai_data->port_config.slimbus.slimbus_dev_id,
- dai_data->port_config.slimbus.slave_dev_pgd_la,
- dai_data->port_config.slimbus.slave_dev_intfdev_la,
- dai_data->port_config.slimbus.bit_width,
- dai_data->port_config.slimbus.data_format,
- dai_data->port_config.slimbus.num_channels,
- dai_data->port_config.slimbus.slave_port_mapping[0],
- dai_data->port_config.slimbus.slave_port_mapping[1],
- dai_data->port_config.slimbus.slave_port_mapping[2],
+ "sample_rate %d\n", __func__,
+ dai_data->port_config.slim_sch.slimbus_dev_id,
+ dai_data->port_config.slim_sch.bit_width,
+ dai_data->port_config.slim_sch.data_format,
+ dai_data->port_config.slim_sch.num_channels,
+ dai_data->port_config.slim_sch.slave_ch_mapping[0],
+ dai_data->port_config.slim_sch.slave_ch_mapping[1],
+ dai_data->port_config.slim_sch.slave_ch_mapping[2],
dai_data->rate);
return 0;
@@ -425,9 +348,6 @@
case MI2S_RX:
rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
break;
- case HDMI_RX:
- rc = msm_dai_q6_hdmi_hw_params(params, dai);
- break;
case SLIMBUS_0_RX:
case SLIMBUS_0_TX:
rc = msm_dai_q6_slim_bus_hw_params(params, dai,
@@ -811,7 +731,8 @@
{
int rc = 0;
- dev_dbg(dai->dev, "enter %s, id = %d\n", __func__, dai->id);
+ dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
+ dai->id, fmt);
switch (dai->id) {
case PRIMARY_I2S_TX:
case PRIMARY_I2S_RX:
@@ -828,12 +749,69 @@
return rc;
}
+static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+
+{
+ int rc = 0;
+ struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ unsigned int i = 0;
+
+ dev_dbg(dai->dev, "enter %s, id = %d\n", __func__,
+ dai->id);
+ if (!tx_slot && !rx_slot)
+ return -EINVAL;
+ switch (dai->id) {
+ case SLIMBUS_0_RX:
+ /* channel number to be between 128 and 255. For RX port
+ * use channel numbers from 138 to 144, for TX port
+ * use channel numbers from 128 to 137
+ */
+ for (i = 0; i < rx_num; i++) {
+ dai_data->port_config.slim_sch.slave_ch_mapping[i] =
+ rx_slot[i];
+ pr_debug("%s: find number of channels[%d] ch[%d]\n",
+ __func__, i,
+ rx_slot[i]);
+ }
+ dai_data->port_config.slim_sch.num_channels = rx_num;
+ pr_debug("%s:SLIMBUS_0_RX cnt[%d] ch[%d %d]\n", __func__,
+ rx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
+ dai_data->port_config.slim_sch.slave_ch_mapping[1]);
+
+ break;
+ case SLIMBUS_0_TX:
+ /* channel number to be between 128 and 255. For RX port
+ * use channel numbers from 138 to 144, for TX port
+ * use channel numbers from 128 to 137
+ */
+ for (i = 0; i < tx_num; i++) {
+ dai_data->port_config.slim_sch.slave_ch_mapping[i] =
+ tx_slot[i];
+ pr_debug("%s: find number of channels[%d] ch[%d]\n",
+ __func__, i, tx_slot[i]);
+ }
+ dai_data->port_config.slim_sch.num_channels = tx_num;
+ pr_debug("%s:SLIMBUS_0_TX cnt[%d] ch[%d %d]\n", __func__,
+ tx_num, dai_data->port_config.slim_sch.slave_ch_mapping[0],
+ dai_data->port_config.slim_sch.slave_ch_mapping[1]);
+ break;
+ default:
+ dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
static struct snd_soc_dai_ops msm_dai_q6_ops = {
.prepare = msm_dai_q6_prepare,
.trigger = msm_dai_q6_trigger,
.hw_params = msm_dai_q6_hw_params,
.shutdown = msm_dai_q6_shutdown,
.set_fmt = msm_dai_q6_set_fmt,
+ .set_channel_map = msm_dai_q6_set_channel_map,
};
static struct snd_soc_dai_ops msm_dai_q6_auxpcm_ops = {
@@ -903,20 +881,6 @@
.remove = msm_dai_q6_dai_remove,
};
-static struct snd_soc_dai_driver msm_dai_q6_hdmi_rx_dai = {
- .playback = {
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .channels_min = 2,
- .channels_max = 2,
- .rate_max = 48000,
- .rate_min = 48000,
- },
- .ops = &msm_dai_q6_ops,
- .probe = msm_dai_q6_dai_probe,
- .remove = msm_dai_q6_dai_remove,
-};
-
static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
.playback = {
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
@@ -1101,9 +1065,6 @@
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_mi2s_rx_dai);
break;
- case HDMI_RX:
- rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_hdmi_rx_dai);
- break;
case SLIMBUS_0_RX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_slimbus_rx_dai);
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
new file mode 100644
index 0000000..1dac5d2
--- /dev/null
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -0,0 +1,723 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/android_pmem.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+
+#include "msm-pcm-q6.h"
+#include "msm-pcm-routing.h"
+
+static struct audio_locks the_locks;
+
+struct snd_msm {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+};
+
+#define PLAYBACK_NUM_PERIODS 8
+#define PLAYBACK_PERIOD_SIZE 4032
+#define CAPTURE_NUM_PERIODS 16
+#define CAPTURE_PERIOD_SIZE 320
+
+static struct snd_pcm_hardware msm_pcm_hardware_capture = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
+ .period_bytes_min = CAPTURE_PERIOD_SIZE,
+ .period_bytes_max = CAPTURE_PERIOD_SIZE,
+ .periods_min = CAPTURE_NUM_PERIODS,
+ .periods_max = CAPTURE_NUM_PERIODS,
+ .fifo_size = 0,
+};
+
+static struct snd_pcm_hardware msm_pcm_hardware_playback = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 6,
+ .buffer_bytes_max = PLAYBACK_NUM_PERIODS * PLAYBACK_PERIOD_SIZE,
+ .period_bytes_min = PLAYBACK_PERIOD_SIZE,
+ .period_bytes_max = PLAYBACK_PERIOD_SIZE,
+ .periods_min = PLAYBACK_NUM_PERIODS,
+ .periods_max = PLAYBACK_NUM_PERIODS,
+ .fifo_size = 0,
+};
+
+/* Conventional and unconventional sample rate supported */
+static unsigned int supported_sample_rates[] = {
+ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+};
+
+static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
+
+static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
+ .count = ARRAY_SIZE(supported_sample_rates),
+ .list = supported_sample_rates,
+ .mask = 0,
+};
+
+static void event_handler(uint32_t opcode,
+ uint32_t token, uint32_t *payload, void *priv)
+{
+ struct msm_audio *prtd = priv;
+ struct snd_pcm_substream *substream = prtd->substream;
+ uint32_t *ptrmem = (uint32_t *)payload;
+ int i = 0;
+ uint32_t idx = 0;
+ uint32_t size = 0;
+
+ pr_debug("%s\n", __func__);
+ switch (opcode) {
+ case ASM_DATA_EVENT_WRITE_DONE: {
+ pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
+ pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
+ prtd->pcm_irq_pos += prtd->pcm_count;
+ if (atomic_read(&prtd->start))
+ snd_pcm_period_elapsed(substream);
+ atomic_inc(&prtd->out_count);
+ wake_up(&the_locks.write_wait);
+ if (!atomic_read(&prtd->start))
+ break;
+ if (!prtd->mmap_flag)
+ break;
+ if (q6asm_is_cpu_buf_avail_nolock(IN,
+ prtd->audio_client,
+ &size, &idx)) {
+ pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
+ __func__, prtd->pcm_count);
+ q6asm_write_nolock(prtd->audio_client,
+ prtd->pcm_count, 0, 0, NO_TIMESTAMP);
+ }
+ break;
+ }
+ case ASM_DATA_CMDRSP_EOS:
+ pr_debug("ASM_DATA_CMDRSP_EOS\n");
+ prtd->cmd_ack = 1;
+ wake_up(&the_locks.eos_wait);
+ break;
+ case ASM_DATA_EVENT_READ_DONE: {
+ pr_debug("ASM_DATA_EVENT_READ_DONE\n");
+ pr_debug("token = 0x%08x\n", token);
+ for (i = 0; i < 8; i++, ++ptrmem)
+ pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
+ in_frame_info[token][0] = payload[2];
+ in_frame_info[token][1] = payload[3];
+ prtd->pcm_irq_pos += in_frame_info[token][0];
+ pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
+ if (atomic_read(&prtd->start))
+ snd_pcm_period_elapsed(substream);
+ if (atomic_read(&prtd->in_count) <= prtd->periods)
+ atomic_inc(&prtd->in_count);
+ wake_up(&the_locks.read_wait);
+ if (prtd->mmap_flag
+ && q6asm_is_cpu_buf_avail_nolock(OUT,
+ prtd->audio_client,
+ &size, &idx))
+ q6asm_read_nolock(prtd->audio_client);
+ break;
+ }
+ case APR_BASIC_RSP_RESULT: {
+ switch (payload[0]) {
+ case ASM_SESSION_CMD_RUN:
+ if (substream->stream
+ != SNDRV_PCM_STREAM_PLAYBACK) {
+ atomic_set(&prtd->start, 1);
+ break;
+ }
+ if (prtd->mmap_flag) {
+ pr_debug("%s:writing %d bytes"
+ " of buffer to dsp\n",
+ __func__,
+ prtd->pcm_count);
+ q6asm_write_nolock(prtd->audio_client,
+ prtd->pcm_count,
+ 0, 0, NO_TIMESTAMP);
+ } else {
+ while (atomic_read(&prtd->out_needed)) {
+ pr_debug("%s:writing %d bytes"
+ " of buffer to dsp\n",
+ __func__,
+ prtd->pcm_count);
+ q6asm_write_nolock(prtd->audio_client,
+ prtd->pcm_count,
+ 0, 0, NO_TIMESTAMP);
+ atomic_dec(&prtd->out_needed);
+ wake_up(&the_locks.write_wait);
+ };
+ }
+ atomic_set(&prtd->start, 1);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
+ break;
+ }
+}
+
+static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ int ret;
+
+ pr_debug("%s\n", __func__);
+ prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+ prtd->pcm_irq_pos = 0;
+ /* rate and channels are sent to audio driver */
+ prtd->samp_rate = runtime->rate;
+ prtd->channel_mode = runtime->channels;
+ if (prtd->enabled)
+ return 0;
+
+ ret = q6asm_media_format_block_multi_ch_pcm(prtd->audio_client,
+ runtime->rate, runtime->channels);
+ if (ret < 0)
+ pr_info("%s: CMD Format block failed\n", __func__);
+
+ atomic_set(&prtd->out_count, runtime->periods);
+
+ prtd->enabled = 1;
+ prtd->cmd_ack = 0;
+
+ return 0;
+}
+
+static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ int ret = 0;
+ int i = 0;
+ pr_debug("%s\n", __func__);
+ prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+ prtd->pcm_irq_pos = 0;
+
+ /* rate and channels are sent to audio driver */
+ prtd->samp_rate = runtime->rate;
+ prtd->channel_mode = runtime->channels;
+
+ if (prtd->enabled)
+ return 0;
+
+ pr_debug("Samp_rate = %d\n", prtd->samp_rate);
+ pr_debug("Channel = %d\n", prtd->channel_mode);
+ ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
+ prtd->channel_mode);
+ if (ret < 0)
+ pr_debug("%s: cmd cfg pcm was block failed", __func__);
+
+ for (i = 0; i < runtime->periods; i++)
+ q6asm_read(prtd->audio_client);
+ prtd->periods = runtime->periods;
+
+ prtd->enabled = 1;
+
+ return ret;
+}
+
+static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int ret = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ pr_debug("%s: Trigger start\n", __func__);
+ q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
+ atomic_set(&prtd->start, 0);
+ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ break;
+ prtd->cmd_ack = 0;
+ q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
+ q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+ atomic_set(&prtd->start, 0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int msm_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct msm_audio *prtd;
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+ prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
+ if (prtd == NULL) {
+ pr_err("Failed to allocate memory for msm_audio\n");
+ return -ENOMEM;
+ }
+ prtd->substream = substream;
+ prtd->audio_client = q6asm_audio_client_alloc(
+ (app_cb)event_handler, prtd);
+ if (!prtd->audio_client) {
+ pr_err("%s: Could not allocate memory\n", __func__);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ runtime->hw = msm_pcm_hardware_playback;
+ ret = q6asm_open_write(prtd->audio_client,
+ FORMAT_MULTI_CHANNEL_LINEAR_PCM);
+ if (ret < 0) {
+ pr_err("%s: pcm out open failed\n", __func__);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ }
+ /* Capture path */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ runtime->hw = msm_pcm_hardware_capture;
+ ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
+ if (ret < 0) {
+ pr_err("%s: pcm in open failed\n", __func__);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ }
+
+ pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
+
+ prtd->session_id = prtd->audio_client->session;
+ msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+ prtd->session_id, substream->stream);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prtd->cmd_ack = 1;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_sample_rates);
+ if (ret < 0)
+ pr_err("snd_pcm_hw_constraint_list failed\n");
+ /* Ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ pr_err("snd_pcm_hw_constraint_integer failed\n");
+
+ prtd->dsp_cnt = 0;
+ runtime->private_data = prtd;
+
+ return 0;
+}
+
+static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
+ snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
+{
+ int ret = 0;
+ int fbytes = 0;
+ int xfer = 0;
+ char *bufptr = NULL;
+ void *data = NULL;
+ uint32_t idx = 0;
+ uint32_t size = 0;
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ fbytes = frames_to_bytes(runtime, frames);
+ pr_debug("%s: prtd->out_count = %d\n",
+ __func__, atomic_read(&prtd->out_count));
+ ret = wait_event_timeout(the_locks.write_wait,
+ (atomic_read(&prtd->out_count)), 5 * HZ);
+ if (ret < 0) {
+ pr_err("%s: wait_event_timeout failed\n", __func__);
+ goto fail;
+ }
+
+ if (!atomic_read(&prtd->out_count)) {
+ pr_err("%s: pcm stopped out_count 0\n", __func__);
+ return 0;
+ }
+
+ data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size, &idx);
+ bufptr = data;
+ if (bufptr) {
+ pr_debug("%s:fbytes =%d: xfer=%d size=%d\n",
+ __func__, fbytes, xfer, size);
+ xfer = fbytes;
+ if (copy_from_user(bufptr, buf, xfer)) {
+ ret = -EFAULT;
+ goto fail;
+ }
+ buf += xfer;
+ fbytes -= xfer;
+ pr_debug("%s:fbytes = %d: xfer=%d\n", __func__, fbytes, xfer);
+ if (atomic_read(&prtd->start)) {
+ pr_debug("%s:writing %d bytes of buffer to dsp\n",
+ __func__, xfer);
+ ret = q6asm_write(prtd->audio_client, xfer,
+ 0, 0, NO_TIMESTAMP);
+ if (ret < 0) {
+ ret = -EFAULT;
+ goto fail;
+ }
+ } else
+ atomic_inc(&prtd->out_needed);
+ atomic_dec(&prtd->out_count);
+ }
+fail:
+ return ret;
+}
+
+static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct msm_audio *prtd = runtime->private_data;
+ int dir = 0;
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+
+ dir = IN;
+ ret = wait_event_timeout(the_locks.eos_wait,
+ prtd->cmd_ack, 5 * HZ);
+ if (ret < 0)
+ pr_err("%s: CMD_EOS failed\n", __func__);
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
+ prtd->audio_client);
+
+ msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return 0;
+}
+
+static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
+ int channel, snd_pcm_uframes_t hwoff, void __user *buf,
+ snd_pcm_uframes_t frames)
+{
+ int ret = 0;
+ int fbytes = 0;
+ int xfer;
+ char *bufptr;
+ void *data = NULL;
+ static uint32_t idx;
+ static uint32_t size;
+ uint32_t offset = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = substream->runtime->private_data;
+
+
+ pr_debug("%s\n", __func__);
+ fbytes = frames_to_bytes(runtime, frames);
+
+ pr_debug("appl_ptr %d\n", (int)runtime->control->appl_ptr);
+ pr_debug("hw_ptr %d\n", (int)runtime->status->hw_ptr);
+ pr_debug("avail_min %d\n", (int)runtime->control->avail_min);
+
+ ret = wait_event_timeout(the_locks.read_wait,
+ (atomic_read(&prtd->in_count)), 5 * HZ);
+ if (ret < 0) {
+ pr_debug("%s: wait_event_timeout failed\n", __func__);
+ goto fail;
+ }
+ if (!atomic_read(&prtd->in_count)) {
+ pr_debug("%s: pcm stopped in_count 0\n", __func__);
+ return 0;
+ }
+ pr_debug("Checking if valid buffer is available...%08x\n",
+ (unsigned int) data);
+ data = q6asm_is_cpu_buf_avail(OUT, prtd->audio_client, &size, &idx);
+ bufptr = data;
+ pr_debug("Size = %d\n", size);
+ pr_debug("fbytes = %d\n", fbytes);
+ pr_debug("idx = %d\n", idx);
+ if (bufptr) {
+ xfer = fbytes;
+ if (xfer > size)
+ xfer = size;
+ offset = in_frame_info[idx][1];
+ pr_debug("Offset value = %d\n", offset);
+ if (copy_to_user(buf, bufptr+offset, xfer)) {
+ pr_err("Failed to copy buf to user\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ fbytes -= xfer;
+ size -= xfer;
+ in_frame_info[idx][1] += xfer;
+ pr_debug("%s:fbytes = %d: size=%d: xfer=%d\n",
+ __func__, fbytes, size, xfer);
+ pr_debug(" Sending next buffer to dsp\n");
+ memset(&in_frame_info[idx], 0,
+ sizeof(uint32_t) * 2);
+ atomic_dec(&prtd->in_count);
+ ret = q6asm_read(prtd->audio_client);
+ if (ret < 0) {
+ pr_err("q6asm read failed\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ } else
+ pr_err("No valid buffer\n");
+
+ pr_debug("Returning from capture_copy... %d\n", ret);
+fail:
+ return ret;
+}
+
+static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct msm_audio *prtd = runtime->private_data;
+ int dir = OUT;
+
+ pr_debug("%s\n", __func__);
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
+ prtd->audio_client);
+ msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+ SNDRV_PCM_STREAM_CAPTURE);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+
+ return 0;
+}
+
+static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
+ snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
+ return ret;
+}
+
+static int msm_pcm_close(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_pcm_playback_close(substream);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = msm_pcm_capture_close(substream);
+ return ret;
+}
+static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_pcm_playback_prepare(substream);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = msm_pcm_capture_prepare(substream);
+ return ret;
+}
+
+static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
+{
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ if (prtd->pcm_irq_pos >= prtd->pcm_size)
+ prtd->pcm_irq_pos = 0;
+
+ pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
+ return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
+}
+
+static int msm_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ int result = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ pr_debug("%s\n", __func__);
+ prtd->mmap_flag = 1;
+
+ if (runtime->dma_addr && runtime->dma_bytes) {
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ result = remap_pfn_range(vma, vma->vm_start,
+ runtime->dma_addr >> PAGE_SHIFT,
+ runtime->dma_bytes,
+ vma->vm_page_prot);
+ } else {
+ pr_err("Physical address or size of buf is NULL");
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+ struct audio_buffer *buf;
+ int dir, ret;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = IN;
+ else
+ dir = OUT;
+
+ ret = q6asm_audio_client_buf_alloc_contiguous(dir,
+ prtd->audio_client,
+ runtime->hw.period_bytes_min,
+ runtime->hw.periods_max);
+ if (ret < 0) {
+ pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
+ return -ENOMEM;
+ }
+ buf = prtd->audio_client->port[dir].buf;
+
+ pr_debug("%s:buf = %p\n", __func__, buf);
+ dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ dma_buf->dev.dev = substream->pcm->card->dev;
+ dma_buf->private_data = NULL;
+ dma_buf->area = buf[0].data;
+ dma_buf->addr = buf[0].phys;
+ dma_buf->bytes = runtime->hw.buffer_bytes_max;
+ if (!dma_buf->area)
+ return -ENOMEM;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ return 0;
+}
+
+static struct snd_pcm_ops msm_pcm_ops = {
+ .open = msm_pcm_open,
+ .copy = msm_pcm_copy,
+ .hw_params = msm_pcm_hw_params,
+ .close = msm_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .prepare = msm_pcm_prepare,
+ .trigger = msm_pcm_trigger,
+ .pointer = msm_pcm_pointer,
+ .mmap = msm_pcm_mmap,
+};
+
+static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ int ret = 0;
+
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ return ret;
+}
+
+static struct snd_soc_platform_driver msm_soc_platform = {
+ .ops = &msm_pcm_ops,
+ .pcm_new = msm_asoc_pcm_new,
+};
+
+static __devinit int msm_pcm_probe(struct platform_device *pdev)
+{
+ pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+ return snd_soc_register_platform(&pdev->dev,
+ &msm_soc_platform);
+}
+
+static int msm_pcm_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_platform(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver msm_pcm_driver = {
+ .driver = {
+ .name = "msm-multi-ch-pcm-dsp",
+ .owner = THIS_MODULE,
+ },
+ .probe = msm_pcm_probe,
+ .remove = __devexit_p(msm_pcm_remove),
+};
+
+static int __init msm_soc_platform_init(void)
+{
+ init_waitqueue_head(&the_locks.enable_wait);
+ init_waitqueue_head(&the_locks.eos_wait);
+ init_waitqueue_head(&the_locks.write_wait);
+ init_waitqueue_head(&the_locks.read_wait);
+
+ return platform_driver_register(&msm_pcm_driver);
+}
+module_init(msm_soc_platform_init);
+
+static void __exit msm_soc_platform_exit(void)
+{
+ platform_driver_unregister(&msm_pcm_driver);
+}
+module_exit(msm_soc_platform_exit);
+
+MODULE_DESCRIPTION("Multi channel PCM module platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 2b4999f..8b6b5f1 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -162,6 +162,7 @@
{
int i, session_type, path_type, port_type;
struct route_payload payload;
+ u32 channels;
if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
/* bad ID assigned in machine driver */
@@ -191,11 +192,23 @@
port_type) && msm_bedais[i].active &&
(test_bit(fedai_id,
&msm_bedais[i].fe_sessions))) {
- adm_open(msm_bedais[i].port_id,
+
+ channels = params_channels(msm_bedais[i].hw_params);
+
+ if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
+ (channels > 2))
+ adm_multi_ch_copp_open(msm_bedais[i].port_id,
+ path_type,
+ params_rate(msm_bedais[i].hw_params),
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ else
+ adm_open(msm_bedais[i].port_id,
path_type,
params_rate(msm_bedais[i].hw_params),
params_channels(msm_bedais[i].hw_params),
DEFAULT_COPP_TOPOLOGY);
+
payload.copp_ids[payload.num_copps++] =
msm_bedais[i].port_id;
}
@@ -243,6 +256,7 @@
static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
{
int session_type, path_type;
+ u32 channels;
pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
@@ -271,10 +285,22 @@
set_bit(val, &msm_bedais[reg].fe_sessions);
if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
INVALID_SESSION) {
- adm_open(msm_bedais[reg].port_id, path_type,
+
+ channels = params_channels(msm_bedais[reg].hw_params);
+
+ if ((session_type == SESSION_TYPE_RX) && (channels > 2))
+ adm_multi_ch_copp_open(msm_bedais[reg].port_id,
+ path_type,
+ params_rate(msm_bedais[reg].hw_params),
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ else
+ adm_open(msm_bedais[reg].port_id,
+ path_type,
params_rate(msm_bedais[reg].hw_params),
params_channels(msm_bedais[reg].hw_params),
DEFAULT_COPP_TOPOLOGY);
+
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type);
}
@@ -1463,6 +1489,7 @@
unsigned int be_id = rtd->dai_link->be_id;
int i, path_type, session_type;
struct msm_pcm_routing_bdai_data *bedai;
+ u32 channels;
if (be_id >= MSM_BACKEND_DAI_MAX) {
pr_err("%s: unexpected be_id %d\n", __func__, be_id);
@@ -1500,10 +1527,22 @@
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
- adm_open(bedai->port_id, path_type,
+
+ channels = params_channels(bedai->hw_params);
+ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
+ (channels > 2))
+ adm_multi_ch_copp_open(bedai->port_id,
+ path_type,
+ params_rate(bedai->hw_params),
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ else
+ adm_open(bedai->port_id,
+ path_type,
params_rate(bedai->hw_params),
params_channels(bedai->hw_params),
DEFAULT_COPP_TOPOLOGY);
+
msm_pcm_routing_build_matrix(i,
fe_dai_map[i][session_type], path_type);
}
diff --git a/sound/soc/msm/msm7201.c b/sound/soc/msm/msm7201.c
index 9e041c7..6408cef 100644
--- a/sound/soc/msm/msm7201.c
+++ b/sound/soc/msm/msm7201.c
@@ -1,6 +1,6 @@
/* linux/sound/soc/msm/msm7201.c
*
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011, 2012 Code Aurora Forum. All rights reserved.
*
* All source code in this file is licensed under the following license except
* where indicated.
@@ -40,6 +40,8 @@
#include <mach/msm_rpcrouter.h>
static struct msm_rpc_endpoint *snd_ep;
+static uint32_t snd_mute_ear_mute;
+static uint32_t snd_mute_mic_mute;
struct msm_snd_rpc_ids {
unsigned long prog;
@@ -99,7 +101,7 @@
* The number of devices supported is 26 (0 to 25)
*/
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 25;
+ uinfo->value.integer.max = 36;
return 0;
}
@@ -107,6 +109,8 @@
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = (uint32_t)snd_rpc_ids.device;
+ ucontrol->value.integer.value[1] = snd_mute_ear_mute;
+ ucontrol->value.integer.value[2] = snd_mute_mic_mute;
return 0;
}
@@ -213,8 +217,11 @@
if (rc < 0) {
printk(KERN_ERR "%s: snd rpc call failed! rc = %d\n",
__func__, rc);
- } else
- printk(KERN_INFO "snd device connected \n");
+ } else {
+ printk(KERN_INFO "snd device connected\n");
+ snd_mute_ear_mute = ucontrol->value.integer.value[1];
+ snd_mute_mic_mute = ucontrol->value.integer.value[2];
+ }
return rc;
}
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 578f819..bedfd68 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -643,6 +643,66 @@
return tabla_cal;
}
+static int msm8960_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+
+ pr_debug("%s: ch=%d\n", __func__,
+ msm8960_slim_0_rx_ch);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n", __func__);
+ goto end;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+ msm8960_slim_0_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+ msm8960_slim_0_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set codec channel map\n",
+ __func__);
+ goto end;
+ }
+ } else {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ msm8960_slim_0_tx_ch, tx_ch, 0 , 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(codec_dai,
+ msm8960_slim_0_tx_ch, tx_ch, 0, 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set codec channel map\n",
+ __func__);
+ goto end;
+ }
+
+
+ }
+end:
+ return ret;
+}
+
static int msm8960_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int err;
@@ -787,8 +847,10 @@
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
+ pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+ channels->min, channels->max);
+
rate->min = rate->max = 48000;
- channels->min = channels->max = 2;
return 0;
}
@@ -912,6 +974,7 @@
static struct snd_soc_ops msm8960_be_ops = {
.startup = msm8960_startup,
+ .hw_params = msm8960_hw_params,
.shutdown = msm8960_shutdown,
};
@@ -936,7 +999,7 @@
.name = "MSM8960 Media2",
.stream_name = "MultiMedia2",
.cpu_dai_name = "MultiMedia2",
- .platform_name = "msm-pcm-dsp",
+ .platform_name = "msm-multi-ch-pcm-dsp",
.dynamic = 1,
.dsp_link = &fe_media,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
@@ -1118,7 +1181,7 @@
{
.name = LPASS_BE_HDMI,
.stream_name = "HDMI Playback",
- .cpu_dai_name = "msm-dai-q6.8",
+ .cpu_dai_name = "msm-dai-q6-hdmi.8",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 177e1d8..2710fbb 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -103,7 +103,8 @@
}
switch (data->opcode) {
- case ADM_CMDRSP_COPP_OPEN: {
+ case ADM_CMDRSP_COPP_OPEN:
+ case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
struct adm_copp_open_respond *open = data->payload;
if (open->copp_id == INVALID_COPP_ID) {
pr_err("%s: invalid coppid rxed %d\n",
@@ -360,6 +361,133 @@
return ret;
}
+
+int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
+ int topology)
+{
+ struct adm_multi_ch_copp_open_command open;
+ int ret = 0;
+ int index;
+
+ pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__,
+ port_id, path, rate, channel_mode);
+
+ port_id = afe_convert_virtual_to_portid(port_id);
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+ return -ENODEV;
+ }
+
+ index = afe_get_port_index(port_id);
+ pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+ if (this_adm.apr == NULL) {
+ this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+ 0xFFFFFFFF, &this_adm);
+ if (this_adm.apr == NULL) {
+ pr_err("%s: Unable to register ADM\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ rtac_set_adm_handle(this_adm.apr);
+ }
+
+ /* Create a COPP if port id are not enabled */
+ if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
+
+ open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+
+ open.hdr.pkt_size =
+ sizeof(struct adm_multi_ch_copp_open_command);
+ open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN;
+ memset(open.dev_channel_mapping, 0, 8);
+
+ if (channel_mode == 1) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 2) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 6) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ } else {
+ pr_err("%s invalid num_chan %d\n", __func__,
+ channel_mode);
+ return -EINVAL;
+ }
+
+
+ open.hdr.src_svc = APR_SVC_ADM;
+ open.hdr.src_domain = APR_DOMAIN_APPS;
+ open.hdr.src_port = port_id;
+ open.hdr.dest_svc = APR_SVC_ADM;
+ open.hdr.dest_domain = APR_DOMAIN_ADSP;
+ open.hdr.dest_port = port_id;
+ open.hdr.token = port_id;
+
+ open.mode = path;
+ open.endpoint_id1 = port_id;
+ open.endpoint_id2 = 0xFFFF;
+
+ /* convert path to acdb path */
+ if (path == ADM_PATH_PLAYBACK)
+ open.topology_id = get_adm_rx_topology();
+ else {
+ open.topology_id = get_adm_tx_topology();
+ if ((open.topology_id ==
+ VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+ (open.topology_id ==
+ VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
+ (open.topology_id ==
+ VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY))
+ rate = 16000;
+ }
+
+ if (open.topology_id == 0)
+ open.topology_id = topology;
+
+ open.channel_config = channel_mode & 0x00FF;
+ open.rate = rate;
+
+ pr_debug("%s: channel_config=%d port_id=%d rate=%d"
+ " topology_id=0x%X\n", __func__, open.channel_config,
+ open.endpoint_id1, open.rate,
+ open.topology_id);
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+ if (ret < 0) {
+ pr_err("%s:ADM enable for port %d failed\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ /* Wait for the callback with copp id */
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s ADM open failed for port %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ }
+ atomic_inc(&this_adm.copp_cnt[index]);
+ return 0;
+
+fail_cmd:
+
+ return ret;
+}
+
int adm_matrix_map(int session_id, int path, int num_copps,
unsigned int *port_id, int copp_id)
{
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 302ef57..59506f1 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -77,6 +77,8 @@
if (data->opcode == APR_BASIC_RSP_RESULT) {
switch (payload[0]) {
case AFE_PORT_AUDIO_IF_CONFIG:
+ case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
+ case AFE_PORT_AUDIO_SLIM_SCH_CONFIG:
case AFE_PORT_CMD_STOP:
case AFE_PORT_CMD_START:
case AFE_PORT_CMD_LOOPBACK:
@@ -280,11 +282,11 @@
ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
break;
case HDMI_RX:
- ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_cfg);
+ ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
break;
case SLIMBUS_0_RX:
case SLIMBUS_0_TX:
- ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_cfg);
+ ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
break;
case RT_PROXY_PORT_001_RX:
case RT_PROXY_PORT_001_TX:
@@ -400,13 +402,41 @@
ret = -ENODEV;
return ret;
}
- config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+
+ if (port_id == HDMI_RX) {
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
- config.hdr.src_port = 0;
- config.hdr.dest_port = 0;
- config.hdr.token = 0;
- config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+ config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = 0;
+ config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
+ } else {
+
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = 0;
+ switch (port_id) {
+ case SLIMBUS_0_RX:
+ case SLIMBUS_0_TX:
+ case SLIMBUS_1_RX:
+ case SLIMBUS_1_TX:
+ case SLIMBUS_2_RX:
+ case SLIMBUS_2_TX:
+ case SLIMBUS_3_RX:
+ case SLIMBUS_3_TX:
+ case SLIMBUS_4_RX:
+ case SLIMBUS_4_TX:
+ config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
+ break;
+ default:
+ config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+ break;
+ }
+ }
if (afe_validate_port(port_id) < 0) {
@@ -472,7 +502,7 @@
return ret;
}
- pr_info("%s: %d %d\n", __func__, port_id, rate);
+ pr_debug("%s: %d %d\n", __func__, port_id, rate);
if ((port_id == RT_PROXY_DAI_001_RX) ||
(port_id == RT_PROXY_DAI_002_TX))
@@ -780,7 +810,7 @@
int ret = 0;
struct afe_pseudoport_start_command start;
- pr_info("%s: port_id=%d\n", __func__, port_id);
+ pr_debug("%s: port_id=%d\n", __func__, port_id);
ret = afe_q6_interface_prepare();
if (ret != 0)
@@ -853,7 +883,7 @@
int ret = 0;
struct afe_pseudoport_stop_command stop;
- pr_info("%s: port_id=%d\n", __func__, port_id);
+ pr_debug("%s: port_id=%d\n", __func__, port_id);
if (this_afe.apr == NULL) {
pr_err("%s: AFE is already closed\n", __func__);
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 62168d2..dc49f12 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -1193,6 +1193,9 @@
case FORMAT_LINEAR_PCM:
open.format = LINEAR_PCM;
break;
+ case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
+ open.format = MULTI_CHANNEL_PCM;
+ break;
case FORMAT_MPEG4_AAC:
open.format = MPEG4_AAC;
break;
@@ -1761,6 +1764,66 @@
return -EINVAL;
}
+int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
+ uint32_t rate, uint32_t channels)
+{
+ struct asm_stream_media_format_update fmt;
+ u8 *channel_mapping;
+ int rc = 0;
+
+ pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
+ channels);
+
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+
+ fmt.format = MULTI_CHANNEL_PCM;
+ fmt.cfg_size = sizeof(struct asm_multi_channel_pcm_fmt_blk);
+ fmt.write_cfg.multi_ch_pcm_cfg.num_channels = channels;
+ fmt.write_cfg.multi_ch_pcm_cfg.bits_per_sample = 16;
+ fmt.write_cfg.multi_ch_pcm_cfg.sample_rate = rate;
+ fmt.write_cfg.multi_ch_pcm_cfg.is_signed = 1;
+ fmt.write_cfg.multi_ch_pcm_cfg.is_interleaved = 1;
+ channel_mapping =
+ fmt.write_cfg.multi_ch_pcm_cfg.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+ if (channels == 1) {
+ channel_mapping[0] = PCM_CHANNEL_FL;
+ } else if (channels == 2) {
+ channel_mapping[0] = PCM_CHANNEL_FL;
+ channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channels == 6) {
+ channel_mapping[0] = PCM_CHANNEL_FC;
+ channel_mapping[1] = PCM_CHANNEL_FL;
+ channel_mapping[2] = PCM_CHANNEL_FR;
+ channel_mapping[3] = PCM_CHANNEL_LB;
+ channel_mapping[4] = PCM_CHANNEL_RB;
+ channel_mapping[5] = PCM_CHANNEL_LFE;
+ } else {
+ pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
+ channels);
+ return -EINVAL;
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s:Comamnd open failed\n", __func__);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg)
{
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 219ae10..d528f4b 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3673,6 +3673,29 @@
EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
/**
+ * snd_soc_dai_get_channel_map - configure DAI audio channel map
+ * @dai: DAI
+ * @tx_num: how many TX channels
+ * @tx_slot: pointer to an array which imply the TX slot number channel
+ * 0~num-1 uses
+ * @rx_num: how many RX channels
+ * @rx_slot: pointer to an array which imply the RX slot number channel
+ * 0~num-1 uses
+ *
+ * configure the relationship between channel number and TDM slot number.
+ */
+int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+{
+ if (dai->driver && dai->driver->ops->get_channel_map)
+ return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
+ rx_num, rx_slot);
+ else
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
+/**
* snd_soc_dai_set_tristate - configure DAI system or master clock.
* @dai: DAI
* @tristate: tristate enable
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index b462639..c03f7ca7 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2,6 +2,7 @@
* soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
*
* Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
@@ -59,8 +60,6 @@
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_supply] = 1,
[snd_soc_dapm_micbias] = 2,
- [snd_soc_dapm_aif_in] = 3,
- [snd_soc_dapm_aif_out] = 3,
[snd_soc_dapm_mic] = 4,
[snd_soc_dapm_mux] = 5,
[snd_soc_dapm_virt_mux] = 5,
@@ -69,6 +68,8 @@
[snd_soc_dapm_mixer] = 7,
[snd_soc_dapm_mixer_named_ctl] = 7,
[snd_soc_dapm_pga] = 8,
+ [snd_soc_dapm_aif_in] = 8,
+ [snd_soc_dapm_aif_out] = 8,
[snd_soc_dapm_adc] = 9,
[snd_soc_dapm_out_drv] = 10,
[snd_soc_dapm_hp] = 10,
@@ -78,6 +79,8 @@
static int dapm_down_seq[] = {
[snd_soc_dapm_pre] = 0,
+ [snd_soc_dapm_aif_in] = 1,
+ [snd_soc_dapm_aif_out] = 1,
[snd_soc_dapm_adc] = 1,
[snd_soc_dapm_hp] = 2,
[snd_soc_dapm_spk] = 2,
@@ -91,8 +94,6 @@
[snd_soc_dapm_mux] = 9,
[snd_soc_dapm_virt_mux] = 9,
[snd_soc_dapm_value_mux] = 9,
- [snd_soc_dapm_aif_in] = 10,
- [snd_soc_dapm_aif_out] = 10,
[snd_soc_dapm_supply] = 11,
[snd_soc_dapm_post] = 12,
};