From patchwork Mon Oct 6 15:37:51 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris BREZILLON X-Patchwork-Id: 5038261 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id BBB81C11AB for ; Mon, 6 Oct 2014 15:38:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 891D820179 for ; Mon, 6 Oct 2014 15:38:12 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 57FE82018E for ; Mon, 6 Oct 2014 15:38:10 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 817996E3D9; Mon, 6 Oct 2014 08:38:06 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail.free-electrons.com (top.free-electrons.com [176.31.233.9]) by gabe.freedesktop.org (Postfix) with ESMTP id E49D36E3C9 for ; Mon, 6 Oct 2014 08:38:04 -0700 (PDT) Received: by mail.free-electrons.com (Postfix, from userid 106) id D6EAE88C; Mon, 6 Oct 2014 17:38:09 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY, URIBL_RHS_DOB autolearn=ham version=3.3.1 Received: from localhost.localdomain (col31-4-88-188-83-94.fbx.proxad.net [88.188.83.94]) by mail.free-electrons.com (Postfix) with ESMTPSA id 3663E78C; Mon, 6 Oct 2014 17:38:09 +0200 (CEST) From: Boris Brezillon To: David Airlie , dri-devel@lists.freedesktop.org Subject: [RFC 5/7] drm: atmel-hlcdc: add DPI support Date: Mon, 6 Oct 2014 17:37:51 +0200 Message-Id: <1412609873-1894-6-git-send-email-boris.brezillon@free-electrons.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1412609873-1894-1-git-send-email-boris.brezillon@free-electrons.com> References: <1412609873-1894-1-git-send-email-boris.brezillon@free-electrons.com> Cc: Laurent Pinchart X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Implement a DPI host in the HLCDC driver. Signed-off-by: Boris Brezillon --- drivers/gpu/drm/atmel-hlcdc/Kconfig | 1 + drivers/gpu/drm/atmel-hlcdc/Makefile | 1 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dpi.c | 212 ++++++++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dpi.c diff --git a/drivers/gpu/drm/atmel-hlcdc/Kconfig b/drivers/gpu/drm/atmel-hlcdc/Kconfig index 942407f..af660e2 100644 --- a/drivers/gpu/drm/atmel-hlcdc/Kconfig +++ b/drivers/gpu/drm/atmel-hlcdc/Kconfig @@ -5,6 +5,7 @@ config DRM_ATMEL_HLCDC select DRM_KMS_HELPER select DRM_KMS_FB_HELPER select DRM_KMS_CMA_HELPER + select DRM_MIPI_DPI select DRM_PANEL select MFD_ATMEL_HLCDC depends on OF diff --git a/drivers/gpu/drm/atmel-hlcdc/Makefile b/drivers/gpu/drm/atmel-hlcdc/Makefile index 10ae426..979e431 100644 --- a/drivers/gpu/drm/atmel-hlcdc/Makefile +++ b/drivers/gpu/drm/atmel-hlcdc/Makefile @@ -1,5 +1,6 @@ atmel-hlcdc-dc-y := atmel_hlcdc_crtc.o \ atmel_hlcdc_dc.o \ + atmel_hlcdc_dpi.o \ atmel_hlcdc_layer.o \ atmel_hlcdc_output.o \ atmel_hlcdc_plane.o diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dpi.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dpi.c new file mode 100644 index 0000000..b563dfc --- /dev/null +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dpi.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2014 Free Electrons + * Copyright (C) 2014 Atmel + * + * Author: Boris BREZILLON + * + * 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 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include + +#include +#include + +#include "atmel_hlcdc_dc.h" + +enum atmel_hlcdc_output_mode { + ATMEL_HLCDC_OUTPUT_FMT_RGB444, + ATMEL_HLCDC_OUTPUT_FMT_RGB565, + ATMEL_HLCDC_OUTPUT_FMT_RGB666, + ATMEL_HLCDC_OUTPUT_FMT_RGB888, +}; + +struct atmel_hlcdc_dpi_host { + struct mipi_dpi_host base; + struct atmel_hlcdc_dc *dc; +}; + +static inline struct atmel_hlcdc_dpi_host * +to_atmel_hlcdc_dpi_host(struct mipi_dpi_host *host) +{ + return container_of(host, struct atmel_hlcdc_dpi_host, base); +} + +static int atmel_hlcdc_dpi_attach(struct mipi_dpi_host *host, + struct mipi_dpi_device *dpi) +{ + return 0; +} + +static int atmel_hlcdc_dpi_detach(struct mipi_dpi_host *host, + struct mipi_dpi_device *dpi) +{ + return 0; +} + +static int atmel_hlcdc_dpi_best_format_exclusive(struct mipi_dpi_host *host, + enum video_bus_format *format) +{ + struct mipi_dpi_device *dpi; + bool agreed = false; + int i; + + for (i = 0; i < host->num_supported_formats; i++) { + enum video_bus_format hfmt = host->supported_formats[i]; + agreed = true; + + list_for_each_entry(dpi, &host->devices, node) { + int j; + + if (!dpi->enabled) + continue; + + for (j = 0; j < dpi->num_supported_formats; j++) { + if (hfmt == dpi->supported_formats[j]) + break; + } + + if (j == dpi->num_supported_formats) { + agreed = false; + break; + } + } + + if (agreed) { + *format = hfmt; + break; + } + } + + if (!agreed) + return -EINVAL; + + list_for_each_entry(dpi, &host->devices, node) { + if (!dpi->enabled) + continue; + + dpi->next_format = *format; + } + + return 0; +} + +static int +atmel_hlcdc_dpi_best_format_non_exclusive(struct mipi_dpi_host *host, + enum video_bus_format *format) +{ + struct mipi_dpi_device *dpi; + int best_format_index = 0; + + list_for_each_entry(dpi, &host->devices, node) { + int i, j; + + if (!dpi->enabled) + continue; + + for (i = 0; i < host->num_supported_formats; i++) { + enum video_bus_format hfmt = host->supported_formats[i]; + for (j = 0; j < dpi->num_supported_formats; j++) { + if (hfmt == dpi->supported_formats[j]) + break; + } + + if (j < dpi->num_supported_formats) { + dpi->next_format = hfmt; + break; + } + } + + if (i > best_format_index) + best_format_index = i; + } + + *format = host->supported_formats[best_format_index]; + + return 0; +} + +static int atmel_hlcdc_dpi_set_format(struct mipi_dpi_host *h, + enum video_bus_format fmt) +{ + struct atmel_hlcdc_dpi_host *host = to_atmel_hlcdc_dpi_host(h); + unsigned int cfg; + + switch (fmt) { + case VIDEO_BUS_FMT_RGB888_1X24: + cfg = ATMEL_HLCDC_OUTPUT_FMT_RGB888; + break; + case VIDEO_BUS_FMT_RGB666_1X18: + cfg = ATMEL_HLCDC_OUTPUT_FMT_RGB666; + break; + case VIDEO_BUS_FMT_RGB565_1X16: + cfg = ATMEL_HLCDC_OUTPUT_FMT_RGB565; + break; + case VIDEO_BUS_FMT_RGB444_1X12: + cfg = ATMEL_HLCDC_OUTPUT_FMT_RGB444; + break; + default: + return -EINVAL; + } + + regmap_update_bits(host->dc->hlcdc->regmap, ATMEL_HLCDC_CFG(5), + ATMEL_HLCDC_MODE_MASK, + cfg << 8); + + return 0; +} + +static const struct mipi_dpi_host_ops atmel_hlcdc_dpi_host_ops = { + .attach = atmel_hlcdc_dpi_attach, + .detach = atmel_hlcdc_dpi_detach, + .best_format = atmel_hlcdc_dpi_best_format_exclusive, + .set_format = atmel_hlcdc_dpi_set_format, +}; + +static const enum video_bus_format atmel_hlcdc_dpi_supported_formats[] = { + VIDEO_BUS_FMT_RGB888_1X24, + VIDEO_BUS_FMT_RGB666_1X18, + VIDEO_BUS_FMT_RGB565_1X16, + VIDEO_BUS_FMT_RGB444_1X12, +}; + +int atmel_hlcdc_dpi_create(struct drm_device *dev) +{ + struct atmel_hlcdc_dc *dc = dev->dev_private; + struct atmel_hlcdc_dpi_host *dpi; + int ret; + + dpi = devm_kzalloc(dev->dev, sizeof(*dpi), GFP_KERNEL); + if (!dpi) + return -ENOMEM; + + mipi_dpi_host_init(&dpi->base); + + dpi->dc = dc; + dpi->base.ddev = dev; + dpi->base.dev = dev->dev; + dpi->base.supported_formats = atmel_hlcdc_dpi_supported_formats; + dpi->base.num_supported_formats = + ARRAY_SIZE(atmel_hlcdc_dpi_supported_formats); + dpi->base.ops = &atmel_hlcdc_dpi_host_ops; + dpi->base.of_node = of_get_child_by_name(dev->dev->of_node, "dpi"); + dpi->base.possible_crtcs = 0x1; + + ret = mipi_dpi_host_register(&dpi->base); + if (ret) + return ret; + + dc->dpi = &dpi->base; + + return 0; +}