From: asheplyakov@yandex.ru To: devel@lists.altlinux.org Cc: Vitaly Chikunov <vt@altlinux.org>, Alexey Sheplyakov <asheplyakov@basealt.ru>, Igor Chudov <nir@basealt.ru>, Evgeny Sinelnikov <sin@basealt.ru>, "Vadim V. Vlasov" <vvv19xx@gmail.com> Subject: [devel] [PATCH 13/35] drm: new bridge driver - stdp4028 Date: Fri, 20 May 2022 20:28:27 +0400 Message-ID: <20220520162849.1554351-14-asheplyakov@yandex.ru> (raw) In-Reply-To: <20220520162849.1554351-1-asheplyakov@yandex.ru> From: "Vadim V. Vlasov" <vvv19xx@gmail.com> MegaChips stdp4028 is LVDS to DP bridge. The driver can work in interrupt or poll mode. Videomodes may be specified in the devicetree or read from EDID. Signed-off-by: Vadim V. Vlasov <vvv19xx@gmail.com> Signed-off-by: Alexey Sheplyakov <asheplyakov@basealt.ru> X-feature-Baikal-M --- drivers/gpu/drm/bridge/Kconfig | 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/stdp4028.c | 486 ++++++++++++++++++++++++++++++ 3 files changed, 495 insertions(+) create mode 100644 drivers/gpu/drm/bridge/stdp4028.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 44ad70939663..3795e7020aec 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -316,6 +316,14 @@ config DRM_TI_TPD12S015 Texas Instruments TPD12S015 HDMI level shifter and ESD protection driver. +config DRM_STDP4028 + tristate "MegaChips STDP4028 DP bridge" + depends on OF + select DRM_KMS_HELPER + select DRM_PANEL + help + MegaChips STDP4028 DP bridge driver + source "drivers/gpu/drm/bridge/analogix/Kconfig" source "drivers/gpu/drm/bridge/adv7511/Kconfig" diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index f2c73683cfcb..9faf98509d2c 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o +obj-$(CONFIG_DRM_STDP4028) += stdp4028.o obj-y += analogix/ obj-y += cadence/ diff --git a/drivers/gpu/drm/bridge/stdp4028.c b/drivers/gpu/drm/bridge/stdp4028.c new file mode 100644 index 000000000000..12b3ff31b213 --- /dev/null +++ b/drivers/gpu/drm/bridge/stdp4028.c @@ -0,0 +1,486 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for MegaChips STDP4028 LVDS to DP display bridge + */ + +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_edid.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + +/* video modes */ +#include <video/display_timing.h> +#include <video/of_display_timing.h> +#include <video/videomode.h> + +#define MAX_PIXEL_CLOCK 330000 + +#define EDID_EXT_BLOCK_CNT 0x7E + +#define STDP4028_PRODUCT_ID_REG 0x00 +#define STDP4028_IRQ_OUT_CONF_REG 0x02 +#define STDP4028_IRQ_STS_REG 0x03 +#define STDP4028_I2C_CTRL_REG 0x08 +#define STDP4028_LVDS_FMT_REG 0x0B +#define STDP4028_LVDS_CTRL0_REG 0x0C +#define STDP4028_DPTX_IRQ_EN_REG 0x3C +#define STDP4028_DPTX_IRQ_STS_REG 0x3D +#define STDP4028_DPTX_STS_REG 0x3E + +#define STDP4028_DPTX_DP_IRQ_EN 0x10 + +#define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x04 +#define STDP4028_DPTX_LINK_CH_IRQ_EN 0x20 +#define STDP4028_DPTX_IRQ_CONFIG \ + (STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN) + +#define STDP4028_DPTX_HOTPLUG_STS 0x02 +#define STDP4028_DPTX_LINK_STS 0x10 +#define STDP4028_CON_STATE_CONNECTED \ + (STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS) + +#define STDP4028_DPTX_HOTPLUG_CH_STS 0x04 +#define STDP4028_DPTX_LINK_CH_STS 0x20 +#define STDP4028_DPTX_IRQ_CLEAR \ + (STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS) + +struct stdp4028 { + struct drm_connector connector; + struct drm_bridge bridge; + struct i2c_client *stdp4028_i2c; + struct i2c_client *edid_i2c; + struct edid *edid; + struct gpio_desc *reset_gpio; + struct mutex lock; + int channels; + int chan_cfg; +}; + +static inline int stdp_read(struct stdp4028 *stdp, int reg) +{ + int ret; + + ret = i2c_smbus_read_word_data(stdp->stdp4028_i2c, reg); + if (ret < 0) + return ret; + return be16_to_cpu(ret); +} + +static inline int stdp_write(struct stdp4028 *stdp, int reg, u16 val) +{ + val = cpu_to_be16(val); + return i2c_smbus_write_word_data(stdp->stdp4028_i2c, reg, val); +} + +#define bridge_to_stdp4028(bridge) \ + container_of(bridge, struct stdp4028, bridge) + +#define connector_to_stdp4028(connector) \ + container_of(connector, struct stdp4028, connector) + +static u8 *stdp4028_get_edid(struct i2c_client *client) +{ + struct i2c_adapter *adapter = client->adapter; + unsigned char start = 0x00; + unsigned int total_size; + u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL); + + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &start, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = EDID_LENGTH, + .buf = block, + } + }; + + if (!block) + return NULL; + + if (i2c_transfer(adapter, msgs, 2) != 2) { + DRM_ERROR("Unable to read EDID.\n"); + goto err; + } + + if (!drm_edid_block_valid(block, 0, false, NULL)) { + DRM_ERROR("Invalid EDID data\n"); + goto err; + } + + total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH; + if (total_size > EDID_LENGTH) { + kfree(block); + block = kmalloc(total_size, GFP_KERNEL); + if (!block) + return NULL; + + /* Yes, read the entire buffer, and do not skip the first + * EDID_LENGTH bytes. + */ + start = 0x00; + msgs[1].len = total_size; + msgs[1].buf = block; + + if (i2c_transfer(adapter, msgs, 2) != 2) { + DRM_ERROR("Unable to read EDID extension blocks.\n"); + goto err; + } + } + + return block; + +err: + kfree(block); + return NULL; +} + +/* + * Get videomode specified in the devicetree. + * Return 1 on success, 0 otherwise. + */ +static int stdp4028_get_of_modes(struct drm_connector *connector) +{ + struct stdp4028 *stdp = connector_to_stdp4028(connector); + struct i2c_client *client = stdp->stdp4028_i2c; + struct drm_display_mode *mode; + struct device_node *np = client->dev.of_node; + struct display_timing timing; + struct videomode video_mode; + int ret; + + ret = of_get_display_timing(np, "panel-timing", &timing); + if (ret < 0) + return 0; + + videomode_from_timing(&timing, &video_mode); + + mode = drm_mode_create(connector->dev); + if (!mode) + return 0; + drm_display_mode_from_videomode(&video_mode, mode); + mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + + drm_mode_probed_add(connector, mode); + return 1; +} + +static int stdp4028_get_modes(struct drm_connector *connector) +{ + struct stdp4028 *stdp; + struct i2c_client *client; + int num_modes = 0; + + stdp = connector_to_stdp4028(connector); + client = stdp->edid_i2c; + + mutex_lock(&stdp->lock); + + num_modes = stdp4028_get_of_modes(connector); + if (num_modes > 0) { + mutex_unlock(&stdp->lock); + return num_modes; + } + + kfree(stdp->edid); + stdp->edid = (struct edid *) stdp4028_get_edid(client); + + if (stdp->edid) { + drm_connector_update_edid_property(connector, stdp->edid); + num_modes = drm_add_edid_modes(connector, stdp->edid); + } + + mutex_unlock(&stdp->lock); + + return num_modes; +} + + +static enum drm_mode_status stdp4028_mode_valid( + struct drm_connector *connector, struct drm_display_mode *mode) +{ + if (mode->clock > MAX_PIXEL_CLOCK) { + DRM_INFO("The pixel clock for the mode %s is too high, and not supported.", + mode->name); + return MODE_CLOCK_HIGH; + } + + return MODE_OK; +} + +static const struct +drm_connector_helper_funcs stdp4028_connector_helper_funcs = { + .get_modes = stdp4028_get_modes, + .mode_valid = stdp4028_mode_valid, +}; + +static enum drm_connector_status stdp4028_detect( + struct drm_connector *connector, bool force) +{ + struct stdp4028 *stdp = connector_to_stdp4028(connector); + s32 link_state; + + link_state = stdp_read(stdp, STDP4028_DPTX_STS_REG); + + if (link_state == STDP4028_CON_STATE_CONNECTED) + return connector_status_connected; + + if (link_state == 0) + return connector_status_disconnected; + + return connector_status_unknown; +} + +static const struct drm_connector_funcs stdp4028_connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = stdp4028_detect, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static irqreturn_t stdp4028_irq_handler(int irq, void *dev_id) +{ + struct stdp4028 *stdp = dev_id; + + mutex_lock(&stdp->lock); + + stdp_write(stdp, STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR); + + mutex_unlock(&stdp->lock); + + if (stdp->connector.dev) + drm_kms_helper_hotplug_event(stdp->connector.dev); + + return IRQ_HANDLED; +} + +static int stdp4028_create_connector(struct drm_bridge *bridge) +{ + int ret; + struct stdp4028 *stdp + = bridge_to_stdp4028(bridge); + struct drm_connector *connector = &stdp->connector; + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + + if (stdp->stdp4028_i2c->irq) + connector->polled = DRM_CONNECTOR_POLL_HPD; + else + connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + drm_connector_helper_add(connector, &stdp4028_connector_helper_funcs); + + ret = drm_connector_init(bridge->dev, connector, + &stdp4028_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort); + if (ret) { + DRM_ERROR("Failed to initialize connector with drm\n"); + return ret; + } + + return drm_connector_attach_encoder(connector, bridge->encoder); +} + +static int stdp4028_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct stdp4028 *stdp + = bridge_to_stdp4028(bridge); + + /* Configures the bridge to re-enable interrupts after each ack. */ + stdp_write(stdp, STDP4028_IRQ_OUT_CONF_REG, STDP4028_DPTX_DP_IRQ_EN); + + /* Enable interrupts */ + stdp_write(stdp, STDP4028_DPTX_IRQ_EN_REG, STDP4028_DPTX_IRQ_CONFIG); + + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + return 0; + + return stdp4028_create_connector(bridge); +} + +static const struct drm_bridge_funcs stdp4028_funcs = { + .attach = stdp4028_attach, +}; + +static int stdp4028_probe(struct i2c_client *stdp4028_i2c, + const struct i2c_device_id *id) +{ + struct device *dev = &stdp4028_i2c->dev; + struct stdp4028 *bridge; + int ret; + u32 edid_i2c_reg, channels, chan_cfg; + enum of_gpio_flags flags; + int reset_gpio, i; + int reg; + + bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); + if (!bridge) + return -ENOMEM; + + mutex_init(&bridge->lock); + + bridge->stdp4028_i2c = stdp4028_i2c; + bridge->bridge.driver_private = bridge; + i2c_set_clientdata(stdp4028_i2c, bridge); + + reset_gpio = of_get_named_gpio_flags(dev->of_node, + "reset-gpios", 0, &flags); + if (gpio_is_valid(reset_gpio)) { + unsigned long gpio_flags; + + /* + * We will set GPIO to "inactive" state instead of toggling + * reset. If the chip is not ready we will return -EPROBE_DEFER + * and retry later. + */ + if (!(flags & OF_GPIO_ACTIVE_LOW)) + gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_LOW; + else + gpio_flags = GPIOF_OUT_INIT_HIGH; + ret = devm_gpio_request_one(dev, reset_gpio, gpio_flags, + "stdp-reset"); + if (ret) { + dev_err(dev, "request GPIO failed (%d)\n", ret); + /* continue anyway */ + } else { + bridge->reset_gpio = gpio_to_desc(reset_gpio); + udelay(100); + } + } else if (reset_gpio == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } + + ret = of_property_read_u32(dev->of_node, "channels", &channels); + if (ret) + channels = 1; + bridge->channels = channels; + + ret = of_property_read_u32(dev->of_node, "chan-cfg", &chan_cfg); + if (ret) + chan_cfg = 0; + bridge->chan_cfg = chan_cfg; + + ret = of_property_read_u32(dev->of_node, "edid-reg", &edid_i2c_reg); + if (ret) { + dev_warn(dev, "edid-reg not specified, assuming 0x50...\n"); + edid_i2c_reg = 0x50; + } + + /* Configure stdp registers */ + reg = stdp_read(bridge, STDP4028_PRODUCT_ID_REG); + if (reg < 0) { + dev_err(dev, "Can't read stdp id (%d)\n", reg); + return -EPROBE_DEFER; /* probably, reset not complete */ + } + + dev_info(dev, "stdp id word: %x\n", reg); + + for (i = 0; i < 10; i++) { + reg = stdp_read(bridge, STDP4028_IRQ_STS_REG); + if (reg > 0 && reg & 0x800) + break; + usleep_range(1000, 1500); + } + dev_dbg(dev, "STDP status word %x (i = %d)\n", reg, i); + stdp_write(bridge, STDP4028_IRQ_STS_REG, 0x800); //clear + /* enable edid addr */ + stdp_write(bridge, STDP4028_I2C_CTRL_REG, (edid_i2c_reg << 1) | 0x400); + + if (channels == 4) + reg = 2; + else if (channels == 2) + reg = 1; + else + reg = 0; + reg |= chan_cfg << 2; + stdp_write(bridge, STDP4028_LVDS_CTRL0_REG, reg); + + bridge->edid_i2c = i2c_new_dummy_device(stdp4028_i2c->adapter, edid_i2c_reg); + + if (!bridge->edid_i2c) + return -ENOMEM; + + bridge->bridge.funcs = &stdp4028_funcs; + bridge->bridge.of_node = dev->of_node; + drm_bridge_add(&bridge->bridge); + + /* Clear pending interrupts since power up. */ + stdp_write(bridge, STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR); + + if (stdp4028_i2c->irq) { + ret = devm_request_threaded_irq(&stdp4028_i2c->dev, + stdp4028_i2c->irq, NULL, + stdp4028_irq_handler, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "stdp-lvds-dp", bridge); + if (ret) + return ret; + + /* enable DPTX IRQs */ + stdp_write(bridge, STDP4028_IRQ_OUT_CONF_REG, + STDP4028_DPTX_DP_IRQ_EN); + stdp_write(bridge, STDP4028_DPTX_IRQ_EN_REG, + STDP4028_DPTX_IRQ_CONFIG); + } + + return 0; +} + +static int stdp4028_remove(struct i2c_client *stdp4028_i2c) +{ + struct stdp4028 *stdp = i2c_get_clientdata(stdp4028_i2c); + + drm_bridge_remove(&stdp->bridge); + i2c_unregister_device(stdp->edid_i2c); + + kfree(stdp->edid); + + return 0; +} + +static const struct i2c_device_id stdp4028_i2c_table[] = { + {"stdp4028-lvds-dp", 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, stdp4028_i2c_table); + +static const struct of_device_id stdp4028_match[] = { + { .compatible = "megachips,stdp4028-lvds-dp" }, + {}, +}; +MODULE_DEVICE_TABLE(of, stdp4028_match); + +static struct i2c_driver stdp4028_driver = { + .id_table = stdp4028_i2c_table, + .probe = stdp4028_probe, + .remove = stdp4028_remove, + .driver = { + .name = "stdp4028-lvds-dp", + .of_match_table = stdp4028_match, + }, +}; +module_i2c_driver(stdp4028_driver); + +MODULE_AUTHOR("Vadim V. Vlasov <vvv19xx at gmail.com>"); +MODULE_DESCRIPTION("STDP4028 LVDS to DP display bridge)"); +MODULE_LICENSE("GPL v2"); -- 2.32.0
next prev parent reply other threads:[~2022-05-20 16:28 UTC|newest] Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-05-20 16:28 [devel] kernel-image-un-def: Baikal-M asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 01/35] net: stmmac: inital support of Baikal-T1/M SoCs GMAC asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 02/35] dt-bindings: dwmac: Add bindings for Baikal-T1/M SoCs asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 03/35] net: stmmac: custom mdio reset for some Baikal-M boards asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 04/35] net: dwmac-baikal: added compatible strings asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 05/35] hwmon: bt1-pvt: access registers via pvt_{readl, writel} helpers asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 06/35] hwmon: bt1-pvt: define pvt_readl/pvt_writel for Baikal-M SoC asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 07/35] hwmon: bt1-pvt: adjusted probing " asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 08/35] hwmon: bt1-pvt: added compatible baikal,pvt asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 09/35] clk: added Baikal-M clock management unit driver asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 10/35] cpufreq-dt: don't load on Baikal-M SoC asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 11/35] usb: dwc3: of-simple: added compatible string for " asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 12/35] arm64: Enable armv8 based Baikal-M SoC support asheplyakov 2022-05-20 16:28 ` asheplyakov [this message] 2022-05-20 16:28 ` [devel] [PATCH 14/35] drm: added Baikal-M SoC video display unit driver asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 15/35] dw-hdmi-ahb-audio: support Baikal-M SoC asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 16/35] Added TF307/TF306 board management controller driver asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 17/35] ALSA: hda: Baikal-M support asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 18/35] [rejected] serial: 8250_dw: verify clock rate in dw8250_set_termios asheplyakov 2022-05-20 16:53 ` Andy Shevchenko 2022-05-20 16:28 ` [devel] [PATCH 19/35] drm/panfrost: forcibly set dma-coherent on Baikal-M asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 20/35] drm/panfrost: disable devfreq " asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 21/35] pm: disable all sleep states on Baikal-M based boards asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 22/35] arm64-stub: fixed secondary cores boot on Baikal-M SoC asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 23/35] efi-rtc: avoid calling efi.get_time " asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 24/35] net: fwnode_get_phy_id: consider all compatible strings asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 25/35] (BROKEN) dwc-i2s: support Baikal-M SoC asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 26/35] input: added TF307 serio PS/2 emulator driver asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 27/35] arm64: added Baikal-M SoC and TF307 board device tree asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 28/35] arm64: device tree: baikal: mark GPU as dma-coherent asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 29/35] arm64: device tree: Baikal-M: fixed PHY binding description asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 30/35] arm64: device tree: Baikal-M: fixed gpio alias asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 31/35] arm64: device tree: Baikal-M: fixed GPU opp_table asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 32/35] arm64: device tree: Baikal-M: fixed CPUs opp_table asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 33/35] arm64: defconfig for Baikal-M support testing asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 34/35] config-aarch64: enable more Baikal-M related drivers asheplyakov 2022-05-20 16:28 ` [devel] [PATCH 35/35] 1:5.17.9-alt2 asheplyakov 2022-05-21 4:04 ` P X 2022-05-21 16:50 ` Alexey Sheplyakov 2022-05-21 16:55 ` [devel] devel-kernel@ Антон Мидюков 2022-05-22 5:51 ` [devel] [PATCH 35/35] 1:5.17.9-alt2 Dmitry V. Levin 2022-05-23 8:51 ` Alexey Sheplyakov 2022-05-23 9:58 ` Dmitry V. Levin 2022-05-23 11:21 ` Alexey Gladkov 2022-05-23 9:47 ` [devel] Baikal-M patches for et101, aqbm1000, tf307 Evgeny Sinelnikov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220520162849.1554351-14-asheplyakov@yandex.ru \ --to=asheplyakov@yandex.ru \ --cc=asheplyakov@basealt.ru \ --cc=devel@lists.altlinux.org \ --cc=nir@basealt.ru \ --cc=sin@basealt.ru \ --cc=vt@altlinux.org \ --cc=vvv19xx@gmail.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
ALT Linux Team development discussions This inbox may be cloned and mirrored by anyone: git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \ devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru public-inbox-index devel Example config snippet for mirrors. Newsgroup available over NNTP: nntp://lore.altlinux.org/org.altlinux.lists.devel AGPL code for this site: git clone https://public-inbox.org/public-inbox.git