Пример #1
0
static ssize_t level_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct lcdfreq_info *info = dev_get_lcdfreq(dev);
	unsigned int value;
	int ret;

	if (!info->enable) {
		dev_err(info->dev, "%s reject. enable flag is %d\n", __func__, info->enable);
		return -EINVAL;
	}

	ret = kstrtoul(buf, 0, (unsigned long *)&value);

	dev_info(info->dev, "%s :: value=%d\n", __func__, value);

	if (value >= LEVEL_MAX)
		return -EINVAL;

	if (value)
		ret = lcdfreq_lock(info->dev, value);
	else
		ret = lcdfreq_lock_free(info->dev);

	if (ret) {
		dev_err(info->dev, "%s skip\n", __func__);
		return -EINVAL;
	}
#ifdef CONFIG_MACH_T0
	tsp_lcd_infom((bool *)value);
#endif
	return count;
}
Пример #2
0
static ssize_t usage_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct lcdfreq_info *info = dev_get_lcdfreq(dev);

	return sprintf(buf, "%d\n", atomic_read(&info->usage));
}
Пример #3
0
static int set_lcdfreq_div(struct device *dev, enum lcdfreq_level level)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);

	u32 ret;

	mutex_lock(&lcdfreq->lock);

	if (!lcdfreq->enable) {
		dev_err(dev, "%s reject. enable flag is %d\n", __func__, lcdfreq->enable);
		ret = -EINVAL;
		goto exit;
	}

	ret = set_div(dev, lcdfreq->table[level].cmu_div);

	if (ret) {
		dev_err(dev, "fail to change lcd freq\n");
		goto exit;
	}

	lcdfreq->level = level;

exit:
	mutex_unlock(&lcdfreq->lock);

	return ret;
}
Пример #4
0
static int get_divider(struct device *dev)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);
	struct clksrc_clk *clksrc;
	struct clk *clk;
	u32 rate, reg;
	u8 fimd_div, i;

	lcdfreq->clksrc = clksrc = get_clksrc(dev->parent);
	clk = clk_get_parent(&clksrc->clk);
	rate = clk_get_rate(clk);

	lcdfreq->table[NORMAL].cmu_div =
		DIV_ROUND_CLOSEST(rate, lcdfreq->table[NORMAL].vclk);

	lcdfreq->table[LIMIT].cmu_div =
		DIV_ROUND_CLOSEST(rate, lcdfreq->table[LIMIT].vclk);

	if (lcdfreq->table[LIMIT].cmu_div > (1 << clksrc->reg_div.size))
		fimd_div = gcd(lcdfreq->table[NORMAL].cmu_div, lcdfreq->table[LIMIT].cmu_div);
	else
		fimd_div = 1;

	dev_info(dev, "%s rate is %d, fimd div=%d\n", clk->name, rate, fimd_div);

	reg = get_fimd_divider(dev) + 1;

	if ((!fimd_div) || (fimd_div > 256) || (fimd_div != reg)) {
		dev_info(dev, "%s skip, fimd div=%d, reg=%d\n", __func__, fimd_div, reg);
		goto err;
	}

	for (i = 0; i < LEVEL_MAX; i++) {
		lcdfreq->table[i].cmu_div /= fimd_div;
		if (lcdfreq->table[i].cmu_div > (1 << clksrc->reg_div.size)) {
			dev_info(fb->dev, "%s skip, cmu div=%d\n", __func__, lcdfreq->table[i].cmu_div);
			goto err;
		}
		dev_info(dev, "%dhz div is %d\n", lcdfreq->table[i].hz, lcdfreq->table[i].cmu_div);
		lcdfreq->table[i].cmu_div--;
	}

	reg = get_div(dev);
	if (lcdfreq->table[NORMAL].cmu_div != reg) {
		dev_info(dev, "%s skip, cmu div=%d, reg=%d\n", __func__, lcdfreq->table[NORMAL].cmu_div, reg);
		goto err;
	}

	for (i = 0; i < LEVEL_MAX; i++) {
		reg = lcdfreq->table[i].cmu_div;
		lcdfreq->table[i].cmu_div = (reg << clksrc->reg_div.size) | reg;
	}

	return 0;

err:
	return -EINVAL;
}
Пример #5
0
static unsigned int get_vstatus(struct device *dev)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);
	u32 reg;

	reg = readl(lcdfreq->ielcd_regs + IELCD_VIDCON1);
	reg &= VIDCON1_VSTATUS_MASK;

	return reg;
}
Пример #6
0
static ssize_t time_in_state_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct lcdfreq_info *info = dev_get_lcdfreq(dev);

	do_time_slice(info->level);

	return sprintf(buf, "%llu %d (60Hz)\n%llu %d (40Hz)\n", 
		(unsigned long long)time_in_state[NORMAL], NORMAL,
		(unsigned long long)time_in_state[LIMIT], LIMIT);
}
Пример #7
0
static unsigned char get_fimd_divider(struct device *dev)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);
	unsigned int reg;

	reg = readl(lcdfreq->fimd_regs + VIDCON0);
	reg &= VIDCON0_CLKVAL_F_MASK;
	reg >>= VIDCON0_CLKVAL_F_SHIFT;

	return reg;
}
Пример #8
0
static ssize_t level_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct lcdfreq_info *info = dev_get_lcdfreq(dev);

	if (!info->enable) {
		dev_err(info->dev, "%s reject. enable flag is %d\n", __func__, info->enable);
		return -EINVAL;
	}

	return sprintf(buf, "%d, div=%d\n", info->table[info->level].hz, get_div(info->dev));
}
Пример #9
0
static int get_div(struct device *dev)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);
	struct clksrc_clk *clksrc = lcdfreq->clksrc;
	u32 reg = __raw_readl(clksrc->reg_div.reg);
	u32 mask = reg_mask(clksrc->reg_div.shift, clksrc->reg_div.size);

	reg &= mask;
	reg >>= clksrc->reg_div.shift;

	return reg;
}
Пример #10
0
static void reset_div(struct device *dev)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);
	struct clksrc_clk *clksrc = lcdfreq->clksrc;
	u32 reg;

	reg = __raw_readl(clksrc->reg_div.reg);
	reg &= ~(0xff);
	reg |= lcdfreq->table[lcdfreq->level].cmu_div;

	writel(reg, clksrc->reg_div.reg);
}
Пример #11
0
static int lcdfreq_lock_free(struct device *dev)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);

	int ret;

	if (atomic_read(&lcdfreq->usage))
		ret = set_lcdfreq_div(dev, NORMAL);
	else {
		dev_err(dev, "lcd freq is already normal state\n");
		return -EINVAL;
	}

	if (!ret) {
		mutex_lock(&lcdfreq->lock);
		atomic_dec(&lcdfreq->usage);
		mutex_unlock(&lcdfreq->lock);
		cancel_delayed_work(&lcdfreq->work);
	}

	return ret;
}
Пример #12
0
static int lcdfreq_lock(struct device *dev)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);

	int ret;

	if (!atomic_read(&lcdfreq->usage))
		ret = set_lcdfreq_div(dev, LIMIT);
	else {
		dev_err(dev, "lcd freq is already limit state\n");
		return -EINVAL;
	}

	if (!ret) {
		mutex_lock(&lcdfreq->lock);
		atomic_inc(&lcdfreq->usage);
		mutex_unlock(&lcdfreq->lock);
		schedule_delayed_work(&lcdfreq->work, 0);
	}

	return ret;
}
Пример #13
0
static int set_div(struct device *dev, u32 div)
{
	struct lcdfreq_info *lcdfreq = dev_get_lcdfreq(dev);
	struct clksrc_clk *clksrc = lcdfreq->clksrc;
	u32 mask = reg_mask(clksrc->reg_div.shift, clksrc->reg_div.size);

	unsigned long flags;
	u32 reg, count = 1000000;

	do {
		spin_lock_irqsave(&lcdfreq->slock, flags);
		reg = __raw_readl(clksrc->reg_div.reg);

		if ((reg & mask) == (div & mask)) {
			spin_unlock_irqrestore(&lcdfreq->slock, flags);
			return -EINVAL;
		}

		reg &= ~(0xff);
		reg |= div;

		if (VSTATUS_IS_ACTIVE(get_vstatus(dev))) {
			if (VSTATUS_IS_FRONT(get_vstatus(dev))) {
				writel(reg, clksrc->reg_div.reg);
				spin_unlock_irqrestore(&lcdfreq->slock, flags);
				dev_info(dev, "%x, %d\n", __raw_readl(clksrc->reg_div.reg), 1000000-count);
				return 0;
			}
		}
		spin_unlock_irqrestore(&lcdfreq->slock, flags);
		count--;
	} while (count);

	dev_err(dev, "%s fail, div=%d\n", __func__, div);

	return -EINVAL;
}