Estou construindo controladores de jogos personalizados no Linux que usam o barramento i2c presente em portas de vídeo, como HDMI, DVI e VGA, em hardware de PC padrão (x86_64).
Gostaria de verificar minhas configurações atuais de velocidade do barramento i2c e talvez alterá-las. Pelo que entendi, essa seria uma configuração de um driver do kernel Linux, embora eu ainda não tenha descoberto, então talvez eu esteja muito enganado.
Então o que eu tentei foi:
lsmod | grep i2c
i2c_algo_bit 16384 1 i915
i2c_i801 36864 0
i2c_smbus 20480 1 i2c_i801
ok, o i2c_algo_bit é o dispositivo que estou usando (eu acho), dei uma olhada no i2c_smbus também.
modinfo i915
modinfo i915 | grep -i "baud \| freq \| hz \| rate \| speed"
Tentei ler as informações dos módulos i2c-i801 e i915, mas não vejo nada que indique a velocidade de barramento definida atualmente. O I2c (DDC) tem várias configurações possíveis, de 50 kHz a 400 kHz. Gostaria de defini-lo para 400 kHz, caso ainda não esteja definido.
Como posso verificar a frequência do barramento i2c? e como posso alterá-la?
Pesquisei sobre isso para um Kernel da série 6.8.0, pois é o que temos atualmente em um sistema Ubuntu 24.04.2 LTS.
O sistema usou uma placa de vídeo Quadro K4200 que expõe um barramento I2C que pode ler a identidade do monitor conectado:
A Quadro K4200 usa o
nouveau
driver, que também tem uma dependência doi2c-algo-bit
módulo, assim como oi915
driver da pergunta.Olhando abaixo
/sys/class/i2c-adapter
para os barramentos I2C fornecidos pela Quadro K4200, não consigo ver nenhum arquivo disponível no espaço do usuário que defina a velocidade do barramento I2C.O código fonte i2c-algo-bit.c mostra um driver bit-banged de software onde o software controla o indivíduo
SCL
eSDA
os sinais no barramento I2C com software usado para inserir atrasos mínimos entre a alternância dos sinais no barramento I2C.struct i2c_algo_bit_data tem o seguinte campo que é usado para controlar o tempo do software:
As funções em i2c-algo-bit.c têm chamadas para
udelay()
, às vezes atrasando foradap->udelay
e outras vezes(adap->udelay + 1) / 2
.O driver i915/display/intel_gmbus.c usado na questão codifica a velocidade do barramento I2C com a seguinte macro:
Que é usado na
intel_gpio_setup
função para inicializar oi2c_algo_bit_data
udelay
:Portanto, a velocidade do barramento I2C usada pelo i915 será de no máximo 50 kHz (já que o tempo de meio ciclo de clock é codificado como 10 microssegundos). A velocidade real do barramento provavelmente será menor, devido aos atrasos de software usados para controlar a temporização.
O
nouveau
driver usado para o Quadro K4200 também codifica o mesmoudelay
valor para o módulo i2c-algo-bit, nanvkm_i2c_bus_ctor
função em nouveau/nvkm/subdev/i2c/bus.cO padrão DDC determina que o hardware deve suportar uma taxa de clock de 100 kHz e que somente a placa gráfica pode ser o mestre (de clock) do barramento I²C. Portanto, seu dispositivo precisa ser capaz de operar em qualquer velocidade de 100 kHz ou menos, incluindo funções I²C complexas, como o alongamento de clock. (Nunca implemente I²C em software. Se o seu microcontrolador não tiver periféricos I²C, use um microcontrolador diferente ou um barramento diferente.)
Se me permite um conselho:
Não .
Eu costumava dar suporte técnico para um dispositivo embarcado que tinha suas próprias EEPROMs no mesmo barramento I²C que também era usado para o cabeçalho mini-HDMI que ele tinha na frente.
Às vezes (como em: vários clientes independentes meus) usar a interface gráfica do usuário enquanto o backend de hardware estava consultando propriedades de hardware das EEPROMs internas fazia com que as EEPROMs interpretassem incorretamente as respostas da memória de tela contendo EDID como comandos de gravação, devido à colisão de tempo das interações de barramento.
E isso acontecia com dispositivos especializados, onde essas transações de barramento não aconteciam mais de uma vez por minuto, talvez. Extrapole para quantas transações seu controlador gerará e qual a probabilidade de você entrar em conflito com a função real do DDC e fazer com que o usuário tenha um dia realmente ruim.
Os drivers de placas de vídeo geralmente apenas bitbang os barramentos I²C e não conseguem reconhecer transações de múltiplas transferências no barramento I²C.
Não tente pendurar um controle de jogo fora da interface da tela. Isso só vai acabar em lágrimas, requer privilégios muito questionáveis para qualquer software que precise interagir com o controle, e adaptadores I²C para USB custam menos de 2€, mesmo nos distribuidores de eletrônicos mais caros, porém confiáveis ; de jeito nenhum o seu "compro um conector de vídeo, encontro uma porta de placa de vídeo não utilizada ou monto um dispositivo de passagem que ainda funciona, embora os sinais de vídeo sejam extremamente sensíveis e tenham largura de banda extremamente alta" chega perto do custo disso.
Se você estiver construindo um controle de jogo para um console dos anos 1980, talvez considere os barramentos específicos que esses consoles tinham – de qualquer forma, você estaria escrevendo um software de baixo nível muito personalizado para eles.
Mais realisticamente, basta fazer o microcontrolador do seu controle de jogo personalizado falar diretamente com USB. A classe Dispositivo de Interface Humana é praticamente a coisa mais simples que você pode implementar em USB. Todas as famílias de microcontroladores relevantes que você usaria para qualquer coisa que não seja produzida aos milhões ou que precise persistir em microwatts contêm membros com hardware USB integrado. Literalmente, qualquer microcontrolador tem uma interface UART; se precisar de algo, você pode conectá-lo à parte traseira do seu PC IBM original.