summaryrefslogblamecommitdiffstats
path: root/drivers/video/tegra/dc/dpaux.c
blob: 5bf125df417b351ea6eaa4b365e237fd51e39084 (plain) (tree)
1
2
3
4


                                 
                                                                      


























                                                                       
                                    



                                                                


                                                            
 
                                





















                                                                              

                                    
                                                                           
     
                                                              
      

                                                         
                         





                                                                      


                                        






                                           

                                        






                                                                       







                                                                            





                                                                     
                             

















                                                                       






                                                     
/*
 * drivers/video/tegra/dc/dpaux.c
 *
 * Copyright (c) 2014 - 2015, NVIDIA CORPORATION, All rights reserved.
 * Author: Animesh Kishore <ankishore@nvidia.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/err.h>

#include "dpaux_regs.h"
#include "dc_priv.h"
#include "dpaux.h"
#include "../../../../arch/arm/mach-tegra/iomap.h"

static const char *const dpaux_clks[TEGRA_DPAUX_INSTANCE_N] = {
	 "dpaux",
	 "dpaux1",
};

#if !defined(CONFIG_TEGRA_NVDISPLAY)
static unsigned long dpaux_base_addr[TEGRA_DPAUX_INSTANCE_N] = {
	TEGRA_DPAUX_BASE,
	TEGRA_DPAUX1_BASE,
};
#endif

static void __iomem *dpaux_baseaddr[TEGRA_DPAUX_INSTANCE_N];

static DEFINE_MUTEX(dpaux_lock);

static inline struct clk *tegra_dpaux_clk_get(enum tegra_dpaux_instance id)
{
	if (id >= TEGRA_DPAUX_INSTANCE_N)
		return ERR_PTR(-EINVAL);

	return clk_get_sys(dpaux_clks[id], NULL);
}

int tegra_dpaux_clk_en(enum tegra_dpaux_instance id)
{
	return clk_prepare_enable(tegra_dpaux_clk_get(id));
}

void tegra_dpaux_clk_dis(enum tegra_dpaux_instance id)
{
	clk_disable_unprepare(tegra_dpaux_clk_get(id));
}

static inline void _tegra_dpaux_pad_power(struct tegra_dc *dc,
					enum tegra_dpaux_instance id, bool on)
{
	void __iomem *regaddr;
#if !defined(CONFIG_TEGRA_NVDISPLAY)
	regaddr = IO_ADDRESS(dpaux_base_addr[id] + DPAUX_HYBRID_SPARE * 4);
#else
	regaddr = dpaux_baseaddr[id] + DPAUX_HYBRID_SPARE * 4;
#endif
	writel((on ? DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP :
		DPAUX_HYBRID_SPARE_PAD_PWR_POWERDOWN),
		regaddr);
}

__maybe_unused
void tegra_dpaux_pad_power(struct tegra_dc *dc,
				enum tegra_dpaux_instance id, bool on)
{
	if (!tegra_platform_is_linsim())
		tegra_dpaux_clk_en(id);

	tegra_dc_io_start(dc);

	mutex_lock(&dpaux_lock);
	_tegra_dpaux_pad_power(dc, id, on);
	mutex_unlock(&dpaux_lock);

	tegra_dc_io_end(dc);
	if (!tegra_platform_is_linsim())
		tegra_dpaux_clk_dis(id);
}

static inline void _tegra_dpaux_config_pad_mode(struct tegra_dc *dc,
					enum tegra_dpaux_instance id,
					enum tegra_dpaux_pad_mode mode)
{
	u32 val;
	void __iomem *regaddr;
#if !defined(CONFIG_TEGRA_NVDISPLAY)
	regaddr = IO_ADDRESS(dpaux_base_addr[id] + DPAUX_HYBRID_PADCTL * 4);
#else
	regaddr = dpaux_baseaddr[id] + DPAUX_HYBRID_PADCTL * 4;
#endif

	val = readl(regaddr);
	val &= ~(DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_ENABLE |
		DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_ENABLE |
		DPAUX_HYBRID_PADCTL_MODE_I2C);
	val |= mode ? (DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_ENABLE |
		DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_ENABLE |
		mode) : 0;
	writel(val, regaddr);
}

__maybe_unused
void tegra_dpaux_config_pad_mode(struct tegra_dc *dc,
					enum tegra_dpaux_instance id,
					enum tegra_dpaux_pad_mode mode)
{
	tegra_dpaux_clk_en(id);
	tegra_dc_io_start(dc);

	mutex_lock(&dpaux_lock);
	_tegra_dpaux_pad_power(dc, id, true);
	_tegra_dpaux_config_pad_mode(dc, id, mode);
	mutex_unlock(&dpaux_lock);

	tegra_dc_io_end(dc);
	tegra_dpaux_clk_dis(id);
}

__maybe_unused
void tegra_set_dpaux_addr(void __iomem *dpaux_base,
			enum tegra_dpaux_instance id)
{
	dpaux_baseaddr[id] = dpaux_base;
}