File Index
Files and directories
Sign in
FILE

apple_dwi_bl.c

File preview with syntax highlighting.

linux-6.19.14/drivers/video/backlight/apple_dwi_bl.c C
  1// SPDX-License-Identifier: GPL-2.0 OR MIT
  2/*
  3 * Driver for backlight controllers attached via Apple DWI 2-wire interface
  4 *
  5 * Copyright (c) 2024 Nick Chan <towinchenmi@gmail.com>
  6 */
  7
  8#include <linux/backlight.h>
  9#include <linux/bitfield.h>
 10#include <linux/device.h>
 11#include <linux/io.h>
 12#include <linux/mod_devicetable.h>
 13#include <linux/module.h>
 14#include <linux/platform_device.h>
 15
 16#define DWI_BL_CTL			0x0
 17#define DWI_BL_CTL_SEND1		BIT(0)
 18#define DWI_BL_CTL_SEND2		BIT(4)
 19#define DWI_BL_CTL_SEND3		BIT(5)
 20#define DWI_BL_CTL_LE_DATA		BIT(6)
 21/* Only used on Apple A9 and later */
 22#define DWI_BL_CTL_SEND4		BIT(12)
 23
 24#define DWI_BL_CMD			0x4
 25#define DWI_BL_CMD_TYPE			GENMASK(31, 28)
 26#define DWI_BL_CMD_TYPE_SET_BRIGHTNESS	0xa
 27#define DWI_BL_CMD_DATA			GENMASK(10, 0)
 28
 29#define DWI_BL_CTL_SEND			(DWI_BL_CTL_SEND1 | \
 30					 DWI_BL_CTL_SEND2 | \
 31					 DWI_BL_CTL_SEND3 | \
 32					 DWI_BL_CTL_LE_DATA | \
 33					 DWI_BL_CTL_SEND4)
 34
 35#define DWI_BL_MAX_BRIGHTNESS		2047
 36
 37struct apple_dwi_bl {
 38	void __iomem *base;
 39};
 40
 41static int dwi_bl_update_status(struct backlight_device *bl)
 42{
 43	struct apple_dwi_bl *dwi_bl = bl_get_data(bl);
 44
 45	int brightness = backlight_get_brightness(bl);
 46
 47	u32 cmd = 0;
 48
 49	cmd |= FIELD_PREP(DWI_BL_CMD_DATA, brightness);
 50	cmd |= FIELD_PREP(DWI_BL_CMD_TYPE, DWI_BL_CMD_TYPE_SET_BRIGHTNESS);
 51
 52	writel(cmd, dwi_bl->base + DWI_BL_CMD);
 53	writel(DWI_BL_CTL_SEND, dwi_bl->base + DWI_BL_CTL);
 54
 55	return 0;
 56}
 57
 58static int dwi_bl_get_brightness(struct backlight_device *bl)
 59{
 60	struct apple_dwi_bl *dwi_bl = bl_get_data(bl);
 61
 62	u32 cmd = readl(dwi_bl->base + DWI_BL_CMD);
 63
 64	return FIELD_GET(DWI_BL_CMD_DATA, cmd);
 65}
 66
 67static const struct backlight_ops dwi_bl_ops = {
 68	.options = BL_CORE_SUSPENDRESUME,
 69	.get_brightness = dwi_bl_get_brightness,
 70	.update_status	= dwi_bl_update_status
 71};
 72
 73static int dwi_bl_probe(struct platform_device *dev)
 74{
 75	struct apple_dwi_bl *dwi_bl;
 76	struct backlight_device *bl;
 77	struct backlight_properties props;
 78	struct resource *res;
 79
 80	dwi_bl = devm_kzalloc(&dev->dev, sizeof(*dwi_bl), GFP_KERNEL);
 81	if (!dwi_bl)
 82		return -ENOMEM;
 83
 84	dwi_bl->base = devm_platform_get_and_ioremap_resource(dev, 0, &res);
 85	if (IS_ERR(dwi_bl->base))
 86		return PTR_ERR(dwi_bl->base);
 87
 88	memset(&props, 0, sizeof(struct backlight_properties));
 89	props.type = BACKLIGHT_PLATFORM;
 90	props.max_brightness = DWI_BL_MAX_BRIGHTNESS;
 91	props.scale = BACKLIGHT_SCALE_LINEAR;
 92
 93	bl = devm_backlight_device_register(&dev->dev, dev->name, &dev->dev,
 94					dwi_bl, &dwi_bl_ops, &props);
 95	if (IS_ERR(bl))
 96		return PTR_ERR(bl);
 97
 98	platform_set_drvdata(dev, dwi_bl);
 99
100	bl->props.brightness = dwi_bl_get_brightness(bl);
101
102	return 0;
103}
104
105static const struct of_device_id dwi_bl_of_match[] = {
106	{ .compatible = "apple,dwi-bl" },
107	{},
108};
109
110MODULE_DEVICE_TABLE(of, dwi_bl_of_match);
111
112static struct platform_driver dwi_bl_driver = {
113	.driver		= {
114		.name	= "apple-dwi-bl",
115		.of_match_table = dwi_bl_of_match
116	},
117	.probe		= dwi_bl_probe,
118};
119
120module_platform_driver(dwi_bl_driver);
121
122MODULE_DESCRIPTION("Apple DWI Backlight Driver");
123MODULE_AUTHOR("Nick Chan <towinchenmi@gmail.com>");
124MODULE_LICENSE("Dual MIT/GPL");
~/ Read-only file preview.