blob: f0b932bb18b39399706c3e105e95e80e1cae34aa [file] [log] [blame]
/* Copyright (c) 2015-2016, The Linux Foundation. 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 "sde_kms.h"
#include "sde_hw_lm.h"
#include "sde_hw_ctl.h"
struct sde_hw_intr *sde_rm_acquire_intr(struct sde_kms *sde_kms)
{
struct sde_hw_intr *hw_intr;
if (!sde_kms) {
DRM_ERROR("Invalid KMS Driver");
return ERR_PTR(-EINVAL);
}
if (sde_kms->hw_res.intr) {
DRM_ERROR("intr already in use ");
return ERR_PTR(-ENODEV);
}
sde_enable(sde_kms);
hw_intr = sde_hw_intr_init(sde_kms->mmio,
sde_kms->catalog);
sde_disable(sde_kms);
if (!IS_ERR_OR_NULL(hw_intr))
sde_kms->hw_res.intr = hw_intr;
return hw_intr;
}
struct sde_hw_intr *sde_rm_get_intr(struct sde_kms *sde_kms)
{
if (!sde_kms) {
DRM_ERROR("Invalid KMS Driver");
return ERR_PTR(-EINVAL);
}
return sde_kms->hw_res.intr;
}
struct sde_hw_ctl *sde_rm_acquire_ctl_path(struct sde_kms *sde_kms,
enum sde_ctl idx)
{
struct sde_hw_ctl *hw_ctl;
if (!sde_kms) {
DRM_ERROR("Invalid KMS driver");
return ERR_PTR(-EINVAL);
}
if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
DRM_ERROR("Invalid Ctl Path Idx %d", idx);
return ERR_PTR(-EINVAL);
}
if (sde_kms->hw_res.ctl[idx]) {
DRM_ERROR("CTL path %d already in use ", idx);
return ERR_PTR(-ENODEV);
}
sde_enable(sde_kms);
hw_ctl = sde_hw_ctl_init(idx, sde_kms->mmio, sde_kms->catalog);
sde_disable(sde_kms);
if (!IS_ERR_OR_NULL(hw_ctl))
sde_kms->hw_res.ctl[idx] = hw_ctl;
return hw_ctl;
}
struct sde_hw_ctl *sde_rm_get_ctl_path(struct sde_kms *sde_kms,
enum sde_ctl idx)
{
if (!sde_kms) {
DRM_ERROR("Invalid KMS Driver");
return ERR_PTR(-EINVAL);
}
if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
DRM_ERROR("Invalid Ctl path Idx %d", idx);
return ERR_PTR(-EINVAL);
}
return sde_kms->hw_res.ctl[idx];
}
void sde_rm_release_ctl_path(struct sde_kms *sde_kms, enum sde_ctl idx)
{
if (!sde_kms) {
DRM_ERROR("Invalid pointer\n");
return;
}
if ((idx == SDE_NONE) || (idx > sde_kms->catalog->ctl_count)) {
DRM_ERROR("Invalid Ctl path Idx %d", idx);
return;
}
}
struct sde_hw_mixer *sde_rm_acquire_mixer(struct sde_kms *sde_kms,
enum sde_lm idx)
{
struct sde_hw_mixer *mixer;
if (!sde_kms) {
DRM_ERROR("Invalid KMS Driver");
return ERR_PTR(-EINVAL);
}
if ((idx == SDE_NONE) || (idx > sde_kms->catalog->mixer_count)) {
DBG("Invalid mixer id %d", idx);
return ERR_PTR(-EINVAL);
}
if (sde_kms->hw_res.mixer[idx]) {
DRM_ERROR("mixer %d already in use ", idx);
return ERR_PTR(-ENODEV);
}
sde_enable(sde_kms);
mixer = sde_hw_lm_init(idx, sde_kms->mmio, sde_kms->catalog);
sde_disable(sde_kms);
if (!IS_ERR_OR_NULL(mixer))
sde_kms->hw_res.mixer[idx] = mixer;
return mixer;
}
struct sde_hw_mixer *sde_rm_get_mixer(struct sde_kms *sde_kms,
enum sde_lm idx)
{
if (!sde_kms) {
DRM_ERROR("Invalid KMS Driver");
return ERR_PTR(-EINVAL);
}
if ((idx == SDE_NONE) || (idx > sde_kms->catalog->mixer_count)) {
DRM_ERROR("Invalid mixer id %d", idx);
return ERR_PTR(-EINVAL);
}
return sde_kms->hw_res.mixer[idx];
}
const struct sde_hw_res_map *sde_rm_get_res_map(struct sde_kms *sde_kms,
enum sde_intf idx)
{
if (!sde_kms) {
DRM_ERROR("Invalid KMS Driver");
return ERR_PTR(-EINVAL);
}
if ((idx == SDE_NONE) || (idx > sde_kms->catalog->intf_count)) {
DRM_ERROR("Invalid intf id %d", idx);
return ERR_PTR(-EINVAL);
}
DBG(" Platform Resource map for INTF %d -> lm %d, pp %d ctl %d",
sde_kms->hw_res.res_table[idx].intf,
sde_kms->hw_res.res_table[idx].lm,
sde_kms->hw_res.res_table[idx].pp,
sde_kms->hw_res.res_table[idx].ctl);
return &(sde_kms->hw_res.res_table[idx]);
}